[Lldb-commits] [lldb] r280751 - *** This commit represents a complete reformatting of the LLDB source code
Kate Stone via lldb-commits
lldb-commits at lists.llvm.org
Tue Sep 6 13:58:36 PDT 2016
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp Tue Sep 6 15:57:50 2016
@@ -1,4 +1,5 @@
-//===-- AppleThreadPlanStepThroughObjCTrampoline.cpp --------------------------*- C++ -*-===//
+//===-- AppleThreadPlanStepThroughObjCTrampoline.cpp
+//--------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,212 +31,183 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// ThreadPlanStepThroughObjCTrampoline constructor
//----------------------------------------------------------------------
-AppleThreadPlanStepThroughObjCTrampoline::AppleThreadPlanStepThroughObjCTrampoline
-(
- Thread &thread,
- AppleObjCTrampolineHandler *trampoline_handler,
- ValueList &input_values,
- lldb::addr_t isa_addr,
- lldb::addr_t sel_addr,
- bool stop_others
-) :
- ThreadPlan (ThreadPlan::eKindGeneric,
- "MacOSX Step through ObjC Trampoline",
- thread,
- eVoteNoOpinion,
- eVoteNoOpinion),
- m_trampoline_handler (trampoline_handler),
- m_args_addr (LLDB_INVALID_ADDRESS),
- m_input_values (input_values),
- m_isa_addr(isa_addr),
- m_sel_addr(sel_addr),
- m_impl_function (NULL),
- m_stop_others (stop_others)
-{
-
-}
+AppleThreadPlanStepThroughObjCTrampoline::
+ AppleThreadPlanStepThroughObjCTrampoline(
+ Thread &thread, AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
+ bool stop_others)
+ : ThreadPlan(ThreadPlan::eKindGeneric,
+ "MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion,
+ eVoteNoOpinion),
+ m_trampoline_handler(trampoline_handler),
+ m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values),
+ m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(NULL),
+ m_stop_others(stop_others) {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-AppleThreadPlanStepThroughObjCTrampoline::~AppleThreadPlanStepThroughObjCTrampoline()
-{
-}
+AppleThreadPlanStepThroughObjCTrampoline::
+ ~AppleThreadPlanStepThroughObjCTrampoline() {}
-void
-AppleThreadPlanStepThroughObjCTrampoline::DidPush ()
-{
- // Setting up the memory space for the called function text might require allocations,
- // i.e. a nested function call. This needs to be done as a PreResumeAction.
- m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeFunctionCaller, (void *) this);
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller ()
-{
- if (!m_func_sp)
- {
- DiagnosticManager diagnostics;
- m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values);
-
- if (m_args_addr == LLDB_INVALID_ADDRESS)
- {
- return false;
- }
- m_impl_function = m_trampoline_handler->GetLookupImplementationFunctionCaller();
- ExecutionContext exc_ctx;
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetStopOthers(m_stop_others);
- m_thread.CalculateExecutionContext(exc_ctx);
- m_func_sp = m_impl_function->GetThreadPlanToCallFunction(exc_ctx, m_args_addr, options, diagnostics);
- m_func_sp->SetOkayToDiscard(true);
- m_thread.QueueThreadPlan(m_func_sp, false);
- }
- return true;
-}
+void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
+ // Setting up the memory space for the called function text might require
+ // allocations,
+ // i.e. a nested function call. This needs to be done as a PreResumeAction.
+ m_thread.GetProcess()->AddPreResumeAction(PreResumeInitializeFunctionCaller,
+ (void *)this);
+}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller() {
+ if (!m_func_sp) {
+ DiagnosticManager diagnostics;
+ m_args_addr =
+ m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values);
-bool
-AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeFunctionCaller(void *void_myself)
-{
- AppleThreadPlanStepThroughObjCTrampoline *myself = static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
- return myself->InitializeFunctionCaller();
-}
-
-void
-AppleThreadPlanStepThroughObjCTrampoline::GetDescription (Stream *s,
- lldb::DescriptionLevel level)
-{
- if (level == lldb::eDescriptionLevelBrief)
- s->Printf("Step through ObjC trampoline");
- else
- {
- s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%" PRIx64 ", sel: 0x%" PRIx64,
- m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
+ if (m_args_addr == LLDB_INVALID_ADDRESS) {
+ return false;
}
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan (Stream *error)
-{
- return true;
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (Event *event_ptr)
-{
- // If we get asked to explain the stop it will be because something went
- // wrong (like the implementation for selector function crashed... We're going
- // to figure out what to do about that, so we do explain the stop.
- return true;
-}
-
-lldb::StateType
-AppleThreadPlanStepThroughObjCTrampoline::GetPlanRunState ()
-{
- return eStateRunning;
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::ShouldStop (Event *event_ptr)
-{
- // First stage: we are still handling the "call a function to get the target of the dispatch"
- if (m_func_sp)
- {
- if (!m_func_sp->IsPlanComplete())
- {
- return false;
- }
- else
- {
- if (!m_func_sp->PlanSucceeded())
- {
- SetPlanComplete(false);
- return true;
- }
- m_func_sp.reset();
- }
+ m_impl_function =
+ m_trampoline_handler->GetLookupImplementationFunctionCaller();
+ ExecutionContext exc_ctx;
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetStopOthers(m_stop_others);
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_func_sp = m_impl_function->GetThreadPlanToCallFunction(
+ exc_ctx, m_args_addr, options, diagnostics);
+ m_func_sp->SetOkayToDiscard(true);
+ m_thread.QueueThreadPlan(m_func_sp, false);
+ }
+ return true;
+}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::
+ PreResumeInitializeFunctionCaller(void *void_myself) {
+ AppleThreadPlanStepThroughObjCTrampoline *myself =
+ static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
+ return myself->InitializeFunctionCaller();
+}
+
+void AppleThreadPlanStepThroughObjCTrampoline::GetDescription(
+ Stream *s, lldb::DescriptionLevel level) {
+ if (level == lldb::eDescriptionLevelBrief)
+ s->Printf("Step through ObjC trampoline");
+ else {
+ s->Printf("Stepping to implementation of ObjC method - obj: 0x%llx, isa: "
+ "0x%" PRIx64 ", sel: 0x%" PRIx64,
+ m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+ m_isa_addr, m_sel_addr);
+ }
+}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan(Stream *error) {
+ return true;
+}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop(
+ Event *event_ptr) {
+ // If we get asked to explain the stop it will be because something went
+ // wrong (like the implementation for selector function crashed... We're
+ // going
+ // to figure out what to do about that, so we do explain the stop.
+ return true;
+}
+
+lldb::StateType AppleThreadPlanStepThroughObjCTrampoline::GetPlanRunState() {
+ return eStateRunning;
+}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
+ // First stage: we are still handling the "call a function to get the target
+ // of the dispatch"
+ if (m_func_sp) {
+ if (!m_func_sp->IsPlanComplete()) {
+ return false;
+ } else {
+ if (!m_func_sp->PlanSucceeded()) {
+ SetPlanComplete(false);
+ return true;
+ }
+ m_func_sp.reset();
}
-
- // Second stage, if all went well with the function calling, then fetch the target address, and
- // queue up a "run to that address" plan.
- if (!m_run_to_sp)
- {
- Value target_addr_value;
- ExecutionContext exc_ctx;
- m_thread.CalculateExecutionContext(exc_ctx);
- m_impl_function->FetchFunctionResults (exc_ctx, m_args_addr, target_addr_value);
- m_impl_function->DeallocateFunctionResults(exc_ctx, m_args_addr);
- lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
- Address target_so_addr;
- target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (target_addr == 0)
- {
- if (log)
- log->Printf("Got target implementation of 0x0, stopping.");
- SetPlanComplete();
- return true;
- }
- if (m_trampoline_handler->AddrIsMsgForward(target_addr))
- {
- if (log)
- log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
-
- SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
- const bool abort_other_plans = false;
- const bool first_insn = true;
- const uint32_t frame_idx = 0;
- m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (abort_other_plans,
- &sc,
- first_insn,
- m_stop_others,
- eVoteNoOpinion,
- eVoteNoOpinion,
- frame_idx);
- m_run_to_sp->SetPrivate(true);
- return false;
- }
-
- if (log)
- log->Printf("Running to ObjC method implementation: 0x%" PRIx64, target_addr);
-
- ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime();
- assert (objc_runtime != NULL);
- objc_runtime->AddToMethodCache (m_isa_addr, m_sel_addr, target_addr);
- if (log)
- log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 "} = addr=0x%" PRIx64 " to cache.", m_isa_addr, m_sel_addr, target_addr);
-
- // Extract the target address from the value:
-
- m_run_to_sp.reset(new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others));
- m_thread.QueueThreadPlan(m_run_to_sp, false);
- m_run_to_sp->SetPrivate(true);
- return false;
+ }
+
+ // Second stage, if all went well with the function calling, then fetch the
+ // target address, and
+ // queue up a "run to that address" plan.
+ if (!m_run_to_sp) {
+ Value target_addr_value;
+ ExecutionContext exc_ctx;
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_impl_function->FetchFunctionResults(exc_ctx, m_args_addr,
+ target_addr_value);
+ m_impl_function->DeallocateFunctionResults(exc_ctx, m_args_addr);
+ lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
+ Address target_so_addr;
+ target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (target_addr == 0) {
+ if (log)
+ log->Printf("Got target implementation of 0x0, stopping.");
+ SetPlanComplete();
+ return true;
}
- else if (m_thread.IsThreadPlanDone(m_run_to_sp.get()))
- {
- // Third stage, work the run to target plan.
- SetPlanComplete();
- return true;
+ if (m_trampoline_handler->AddrIsMsgForward(target_addr)) {
+ if (log)
+ log->Printf(
+ "Implementation lookup returned msgForward function: 0x%" PRIx64
+ ", stopping.",
+ target_addr);
+
+ SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(
+ eSymbolContextEverything);
+ const bool abort_other_plans = false;
+ const bool first_insn = true;
+ const uint32_t frame_idx = 0;
+ m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
+ abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
+ eVoteNoOpinion, frame_idx);
+ m_run_to_sp->SetPrivate(true);
+ return false;
}
+
+ if (log)
+ log->Printf("Running to ObjC method implementation: 0x%" PRIx64,
+ target_addr);
+
+ ObjCLanguageRuntime *objc_runtime =
+ GetThread().GetProcess()->GetObjCLanguageRuntime();
+ assert(objc_runtime != NULL);
+ objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr);
+ if (log)
+ log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64
+ "} = addr=0x%" PRIx64 " to cache.",
+ m_isa_addr, m_sel_addr, target_addr);
+
+ // Extract the target address from the value:
+
+ m_run_to_sp.reset(
+ new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others));
+ m_thread.QueueThreadPlan(m_run_to_sp, false);
+ m_run_to_sp->SetPrivate(true);
return false;
+ } else if (m_thread.IsThreadPlanDone(m_run_to_sp.get())) {
+ // Third stage, work the run to target plan.
+ SetPlanComplete();
+ return true;
+ }
+ return false;
}
// The base class MischiefManaged does some cleanup - so you have to call it
// in your MischiefManaged derived class.
-bool
-AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged ()
-{
- if (IsPlanComplete())
- return true;
- else
- return false;
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::WillStop()
-{
+bool AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged() {
+ if (IsPlanComplete())
return true;
+ else
+ return false;
}
+
+bool AppleThreadPlanStepThroughObjCTrampoline::WillStop() { return true; }
Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h Tue Sep 6 15:57:50 2016
@@ -14,80 +14,66 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-types.h"
-#include "lldb/lldb-enumerations.h"
+#include "AppleObjCTrampolineHandler.h"
#include "lldb/Core/Value.h"
#include "lldb/Target/ThreadPlan.h"
-#include "AppleObjCTrampolineHandler.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
-namespace lldb_private
-{
+namespace lldb_private {
-class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan
-{
+class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan {
public:
- AppleThreadPlanStepThroughObjCTrampoline(Thread &thread,
- AppleObjCTrampolineHandler *trampoline_handler,
- ValueList &values,
- lldb::addr_t isa_addr,
- lldb::addr_t sel_addr,
- bool stop_others);
-
- ~AppleThreadPlanStepThroughObjCTrampoline() override;
-
- static bool
- PreResumeInitializeFunctionCaller(void *myself);
-
- void
- GetDescription(Stream *s,
- lldb::DescriptionLevel level) override;
-
- bool
- ValidatePlan(Stream *error) override;
-
- lldb::StateType
- GetPlanRunState() override;
-
- bool
- ShouldStop(Event *event_ptr) override;
-
- bool
- StopOthers() override
- {
- return m_stop_others;
- }
-
- // The base class MischiefManaged does some cleanup - so you have to call it
- // in your MischiefManaged derived class.
- bool
- MischiefManaged() override;
-
- void
- DidPush() override;
-
- bool
- WillStop() override;
+ AppleThreadPlanStepThroughObjCTrampoline(
+ Thread &thread, AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
+ bool stop_others);
+
+ ~AppleThreadPlanStepThroughObjCTrampoline() override;
+
+ static bool PreResumeInitializeFunctionCaller(void *myself);
+
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
+
+ bool ValidatePlan(Stream *error) override;
+
+ lldb::StateType GetPlanRunState() override;
+
+ bool ShouldStop(Event *event_ptr) override;
+
+ bool StopOthers() override { return m_stop_others; }
+
+ // The base class MischiefManaged does some cleanup - so you have to call it
+ // in your MischiefManaged derived class.
+ bool MischiefManaged() override;
+
+ void DidPush() override;
+
+ bool WillStop() override;
protected:
- bool
- DoPlanExplainsStop(Event *event_ptr) override;
-
+ bool DoPlanExplainsStop(Event *event_ptr) override;
+
private:
- bool
- InitializeFunctionCaller ();
+ bool InitializeFunctionCaller();
- AppleObjCTrampolineHandler *m_trampoline_handler; // FIXME - ensure this doesn't go away on us? SP maybe?
- lldb::addr_t m_args_addr; // Stores the address for our step through function result structure.
- //lldb::addr_t m_object_addr; // This is only for Description.
- ValueList m_input_values;
- lldb::addr_t m_isa_addr; // isa_addr and sel_addr are the keys we will use to cache the implementation.
- lldb::addr_t m_sel_addr;
- lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it at start, then set it
- // to NULL when this plan is done. That way we know to go to:
- lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
- FunctionCaller *m_impl_function; // This is a pointer to a impl function that
- // is owned by the client that pushes this plan.
- bool m_stop_others;
+ AppleObjCTrampolineHandler *m_trampoline_handler; // FIXME - ensure this
+ // doesn't go away on us?
+ // SP maybe?
+ lldb::addr_t m_args_addr; // Stores the address for our step through function
+ // result structure.
+ // lldb::addr_t m_object_addr; // This is only for Description.
+ ValueList m_input_values;
+ lldb::addr_t m_isa_addr; // isa_addr and sel_addr are the keys we will use to
+ // cache the implementation.
+ lldb::addr_t m_sel_addr;
+ lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it
+ // at start, then set it
+ // to NULL when this plan is done. That way we know to go to:
+ lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
+ FunctionCaller *m_impl_function; // This is a pointer to a impl function that
+ // is owned by the client that pushes this plan.
+ bool m_stop_others;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp Tue Sep 6 15:57:50 2016
@@ -37,165 +37,163 @@ using namespace lldb_private;
using namespace lldb_renderscript;
// [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang),
-// the compiler frontend for RenderScript embeds an ARM specific triple in IR that is shipped in the app, after
+// the compiler frontend for RenderScript embeds an ARM specific triple in IR
+// that is shipped in the app, after
// generating IR that has some assumptions that an ARM device is the target.
-// As the IR is then compiled on a device of unknown (at time the IR was generated at least) architecture,
-// when calling RenderScript API function as part of debugger expressions, we have to perform a fixup pass that
-// removes those assumptions right before the module is sent to be generated by the llvm backend.
-
-namespace
-{
-bool
-registerRSDefaultTargetOpts(clang::TargetOptions &proto, const llvm::Triple::ArchType &arch)
-{
- switch (arch)
- {
- case llvm::Triple::ArchType::x86:
- proto.Triple = "i686--linux-android";
- proto.CPU = "atom";
- proto.Features.push_back("+long64");
- // Fallthrough for common x86 family features
- case llvm::Triple::ArchType::x86_64:
- proto.Features.push_back("+mmx");
- proto.Features.push_back("+sse");
- proto.Features.push_back("+sse2");
- proto.Features.push_back("+sse3");
- proto.Features.push_back("+ssse3");
- proto.Features.push_back("+sse4.1");
- proto.Features.push_back("+sse4.2");
- break;
- case llvm::Triple::ArchType::mipsel:
- // pretend this is `arm' for the front-end
- proto.Triple = "armv7-none-linux-android";
- proto.CPU = "";
- proto.Features.push_back("+long64");
- break;
- case llvm::Triple::ArchType::mips64el:
- // pretend this is `aarch64' for the front-end
- proto.Triple = "aarch64-none-linux-android";
- proto.CPU = "";
- break;
- default:
- return false;
- }
- return true;
+// As the IR is then compiled on a device of unknown (at time the IR was
+// generated at least) architecture,
+// when calling RenderScript API function as part of debugger expressions, we
+// have to perform a fixup pass that
+// removes those assumptions right before the module is sent to be generated by
+// the llvm backend.
+
+namespace {
+bool registerRSDefaultTargetOpts(clang::TargetOptions &proto,
+ const llvm::Triple::ArchType &arch) {
+ switch (arch) {
+ case llvm::Triple::ArchType::x86:
+ proto.Triple = "i686--linux-android";
+ proto.CPU = "atom";
+ proto.Features.push_back("+long64");
+ // Fallthrough for common x86 family features
+ case llvm::Triple::ArchType::x86_64:
+ proto.Features.push_back("+mmx");
+ proto.Features.push_back("+sse");
+ proto.Features.push_back("+sse2");
+ proto.Features.push_back("+sse3");
+ proto.Features.push_back("+ssse3");
+ proto.Features.push_back("+sse4.1");
+ proto.Features.push_back("+sse4.2");
+ break;
+ case llvm::Triple::ArchType::mipsel:
+ // pretend this is `arm' for the front-end
+ proto.Triple = "armv7-none-linux-android";
+ proto.CPU = "";
+ proto.Features.push_back("+long64");
+ break;
+ case llvm::Triple::ArchType::mips64el:
+ // pretend this is `aarch64' for the front-end
+ proto.Triple = "aarch64-none-linux-android";
+ proto.CPU = "";
+ break;
+ default:
+ return false;
+ }
+ return true;
}
} // end anonymous namespace
-bool
-RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module)
-{
- bool changed_module = false;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
-
- std::string err;
- llvm::StringRef real_triple = m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple();
- const llvm::Target *target_info = llvm::TargetRegistry::lookupTarget(real_triple, err);
- if (!target_info)
- {
- if (log)
- log->Warning("couldn't determine real target architecture: '%s'", err.c_str());
- return false;
- }
-
- llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None;
- assert(m_process_ptr && "no available lldb process");
- switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine())
- {
- case llvm::Triple::ArchType::x86:
- changed_module |= fixupX86FunctionCalls(module);
- // For some reason this triple gets totally missed by the backend, and must be set manually.
- // There a reference in bcc/Main.cpp about auto feature-detection being removed from LLVM3.5, but I can't
- // see that discussion anywhere public.
- real_triple = "i686--linux-android";
- break;
- case llvm::Triple::ArchType::x86_64:
- changed_module |= fixupX86_64FunctionCalls(module);
- break;
- case llvm::Triple::ArchType::mipsel:
- case llvm::Triple::ArchType::mips64el:
- // No actual IR fixup pass is needed on MIPS, but the datalayout
- // and targetmachine do need to be explicitly set.
-
- // bcc explicitly compiles MIPS code to use the static relocation
- // model due to an issue with relocations in mclinker.
- // see libbcc/support/CompilerConfig.cpp for details
- reloc_model = llvm::Reloc::Static;
- changed_module = true;
- break;
- case llvm::Triple::ArchType::arm:
- case llvm::Triple::ArchType::aarch64:
- // ARM subtargets need no fixup passes as they are the initial target as generated by the
- // slang compiler frontend.
- break;
- default:
- if (log)
- log->Warning("Ignoring unknown renderscript target");
- return false;
+bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
+ bool changed_module = false;
+ Log *log(
+ GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
+
+ std::string err;
+ llvm::StringRef real_triple =
+ m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple();
+ const llvm::Target *target_info =
+ llvm::TargetRegistry::lookupTarget(real_triple, err);
+ if (!target_info) {
+ if (log)
+ log->Warning("couldn't determine real target architecture: '%s'",
+ err.c_str());
+ return false;
+ }
+
+ llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None;
+ assert(m_process_ptr && "no available lldb process");
+ switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) {
+ case llvm::Triple::ArchType::x86:
+ changed_module |= fixupX86FunctionCalls(module);
+ // For some reason this triple gets totally missed by the backend, and must
+ // be set manually.
+ // There a reference in bcc/Main.cpp about auto feature-detection being
+ // removed from LLVM3.5, but I can't
+ // see that discussion anywhere public.
+ real_triple = "i686--linux-android";
+ break;
+ case llvm::Triple::ArchType::x86_64:
+ changed_module |= fixupX86_64FunctionCalls(module);
+ break;
+ case llvm::Triple::ArchType::mipsel:
+ case llvm::Triple::ArchType::mips64el:
+ // No actual IR fixup pass is needed on MIPS, but the datalayout
+ // and targetmachine do need to be explicitly set.
+
+ // bcc explicitly compiles MIPS code to use the static relocation
+ // model due to an issue with relocations in mclinker.
+ // see libbcc/support/CompilerConfig.cpp for details
+ reloc_model = llvm::Reloc::Static;
+ changed_module = true;
+ break;
+ case llvm::Triple::ArchType::arm:
+ case llvm::Triple::ArchType::aarch64:
+ // ARM subtargets need no fixup passes as they are the initial target as
+ // generated by the
+ // slang compiler frontend.
+ break;
+ default:
+ if (log)
+ log->Warning("Ignoring unknown renderscript target");
+ return false;
+ }
+
+ if (changed_module) {
+ llvm::TargetOptions options;
+ llvm::TargetMachine *target_machine = target_info->createTargetMachine(
+ real_triple, "", "", options, reloc_model);
+ assert(target_machine &&
+ "failed to identify RenderScriptRuntime target machine");
+ // We've been using a triple and datalayout of some ARM variant all along,
+ // so
+ // we need to let the backend know that this is no longer the case.
+ if (log) {
+ log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__,
+ real_triple.str().c_str());
+ log->Printf(
+ "%s - Changing RS datalayout to '%s'", __FUNCTION__,
+ target_machine->createDataLayout().getStringRepresentation().c_str());
}
-
- if (changed_module)
- {
- llvm::TargetOptions options;
- llvm::TargetMachine *target_machine =
- target_info->createTargetMachine(real_triple, "", "", options, reloc_model);
- assert(target_machine && "failed to identify RenderScriptRuntime target machine");
- // We've been using a triple and datalayout of some ARM variant all along, so
- // we need to let the backend know that this is no longer the case.
- if (log)
- {
- log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, real_triple.str().c_str());
- log->Printf("%s - Changing RS datalayout to '%s'", __FUNCTION__,
- target_machine->createDataLayout().getStringRepresentation().c_str());
- }
- module.setTargetTriple(real_triple);
- module.setDataLayout(target_machine->createDataLayout());
- }
- return changed_module;
+ module.setTargetTriple(real_triple);
+ module.setDataLayout(target_machine->createDataLayout());
+ }
+ return changed_module;
}
char RenderScriptRuntimeModulePass::ID = 0;
-namespace lldb_private
-{
+namespace lldb_private {
-bool
-RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto)
-{
- auto *process = GetProcess();
- assert(process);
- return registerRSDefaultTargetOpts(proto, process->GetTarget().GetArchitecture().GetMachine());
+bool RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) {
+ auto *process = GetProcess();
+ assert(process);
+ return registerRSDefaultTargetOpts(
+ proto, process->GetTarget().GetArchitecture().GetMachine());
}
-bool
-RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes)
-{
- if (!m_ir_passes)
- m_ir_passes = new RSIRPasses(GetProcess());
- assert(m_ir_passes);
+bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) {
+ if (!m_ir_passes)
+ m_ir_passes = new RSIRPasses(GetProcess());
+ assert(m_ir_passes);
- passes.EarlyPasses = m_ir_passes->EarlyPasses;
- passes.LatePasses = m_ir_passes->LatePasses;
+ passes.EarlyPasses = m_ir_passes->EarlyPasses;
+ passes.LatePasses = m_ir_passes->LatePasses;
- return true;
+ return true;
}
-namespace lldb_renderscript
-{
+namespace lldb_renderscript {
-RSIRPasses::RSIRPasses(Process *process)
-{
- IRPasses();
- assert(process);
-
- EarlyPasses = std::make_shared<llvm::legacy::PassManager>();
- assert(EarlyPasses);
- EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
-}
+RSIRPasses::RSIRPasses(Process *process) {
+ IRPasses();
+ assert(process);
-RSIRPasses::~RSIRPasses()
-{
+ EarlyPasses = std::make_shared<llvm::legacy::PassManager>();
+ assert(EarlyPasses);
+ EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
}
+RSIRPasses::~RSIRPasses() {}
+
} // namespace lldb_renderscript
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h Tue Sep 6 15:57:50 2016
@@ -26,34 +26,33 @@
#include "RenderScriptRuntime.h"
#include "RenderScriptx86ABIFixups.h"
-// RenderScriptRuntimeModulePass is a simple llvm::ModulesPass that is used during expression evaluation to apply
+// RenderScriptRuntimeModulePass is a simple llvm::ModulesPass that is used
+// during expression evaluation to apply
// RenderScript-specific fixes for expression evaluation.
-// In particular this is used to make expression IR conformant with the ABI generated by the slang frontend. This
-// ModulePass is executed in ClangExpressionParser::PrepareForExecution whenever an expression's DWARF language is
+// In particular this is used to make expression IR conformant with the ABI
+// generated by the slang frontend. This
+// ModulePass is executed in ClangExpressionParser::PrepareForExecution whenever
+// an expression's DWARF language is
// eLanguageTypeExtRenderscript
-class RenderScriptRuntimeModulePass : public llvm::ModulePass
-{
+class RenderScriptRuntimeModulePass : public llvm::ModulePass {
public:
- static char ID;
- RenderScriptRuntimeModulePass(const lldb_private::Process *process) : ModulePass(ID), m_process_ptr(process) {}
+ static char ID;
+ RenderScriptRuntimeModulePass(const lldb_private::Process *process)
+ : ModulePass(ID), m_process_ptr(process) {}
- bool
- runOnModule(llvm::Module &module);
+ bool runOnModule(llvm::Module &module);
private:
- const lldb_private::Process *m_process_ptr;
+ const lldb_private::Process *m_process_ptr;
};
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
-struct RSIRPasses : public lldb_private::LLVMUserExpression::IRPasses
-{
- RSIRPasses(lldb_private::Process *process);
+namespace lldb_private {
+namespace lldb_renderscript {
+struct RSIRPasses : public lldb_private::LLVMUserExpression::IRPasses {
+ RSIRPasses(lldb_private::Process *process);
- ~RSIRPasses();
+ ~RSIRPasses();
};
} // namespace lldb_renderscript
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp Tue Sep 6 15:57:50 2016
@@ -41,652 +41,596 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_renderscript;
-namespace
-{
+namespace {
// The empirical_type adds a basic level of validation to arbitrary data
// allowing us to track if data has been discovered and stored or not.
-// An empirical_type will be marked as valid only if it has been explicitly assigned to.
-template <typename type_t> class empirical_type
-{
+// An empirical_type will be marked as valid only if it has been explicitly
+// assigned to.
+template <typename type_t> class empirical_type {
public:
- // Ctor. Contents is invalid when constructed.
- empirical_type() : valid(false) {}
+ // Ctor. Contents is invalid when constructed.
+ empirical_type() : valid(false) {}
- // Return true and copy contents to out if valid, else return false.
- bool
- get(type_t &out) const
- {
- if (valid)
- out = data;
- return valid;
- }
-
- // Return a pointer to the contents or nullptr if it was not valid.
- const type_t *
- get() const
- {
- return valid ? &data : nullptr;
- }
-
- // Assign data explicitly.
- void
- set(const type_t in)
- {
- data = in;
- valid = true;
- }
-
- // Mark contents as invalid.
- void
- invalidate()
- {
- valid = false;
- }
-
- // Returns true if this type contains valid data.
- bool
- isValid() const
- {
- return valid;
- }
-
- // Assignment operator.
- empirical_type<type_t> &
- operator=(const type_t in)
- {
- set(in);
- return *this;
- }
-
- // Dereference operator returns contents.
- // Warning: Will assert if not valid so use only when you know data is valid.
- const type_t &operator*() const
- {
- assert(valid);
- return data;
- }
+ // Return true and copy contents to out if valid, else return false.
+ bool get(type_t &out) const {
+ if (valid)
+ out = data;
+ return valid;
+ }
+
+ // Return a pointer to the contents or nullptr if it was not valid.
+ const type_t *get() const { return valid ? &data : nullptr; }
+
+ // Assign data explicitly.
+ void set(const type_t in) {
+ data = in;
+ valid = true;
+ }
+
+ // Mark contents as invalid.
+ void invalidate() { valid = false; }
+
+ // Returns true if this type contains valid data.
+ bool isValid() const { return valid; }
+
+ // Assignment operator.
+ empirical_type<type_t> &operator=(const type_t in) {
+ set(in);
+ return *this;
+ }
+
+ // Dereference operator returns contents.
+ // Warning: Will assert if not valid so use only when you know data is valid.
+ const type_t &operator*() const {
+ assert(valid);
+ return data;
+ }
protected:
- bool valid;
- type_t data;
+ bool valid;
+ type_t data;
};
-// ArgItem is used by the GetArgs() function when reading function arguments from the target.
-struct ArgItem
-{
- enum
- {
- ePointer,
- eInt32,
- eInt64,
- eLong,
- eBool
- } type;
+// ArgItem is used by the GetArgs() function when reading function arguments
+// from the target.
+struct ArgItem {
+ enum { ePointer, eInt32, eInt64, eLong, eBool } type;
- uint64_t value;
+ uint64_t value;
- explicit operator uint64_t() const { return value; }
+ explicit operator uint64_t() const { return value; }
};
-// Context structure to be passed into GetArgsXXX(), argument reading functions below.
-struct GetArgsCtx
-{
- RegisterContext *reg_ctx;
- Process *process;
+// Context structure to be passed into GetArgsXXX(), argument reading functions
+// below.
+struct GetArgsCtx {
+ RegisterContext *reg_ctx;
+ Process *process;
};
-bool
-GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- Error error;
-
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
+bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- for (size_t i = 0; i < num_args; ++i)
- {
- ArgItem &arg = arg_list[i];
- // advance up the stack by one argument
- sp += sizeof(uint32_t);
- // get the argument type size
- size_t arg_size = sizeof(uint32_t);
- // read the argument from memory
- arg.value = 0;
- Error error;
- size_t read = ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), error);
- if (read != arg_size || !error.Success())
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64 " '%s'", __FUNCTION__, uint64_t(i),
- error.AsCString());
- return false;
- }
- }
- return true;
-}
+ Error error;
-bool
-GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 6;
- // register passing order
- static const std::array<const char *, c_args_in_reg> c_reg_names{{"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
- // argument type to size mapping
- static const std::array<size_t, 5> arg_size{{
- 8, // ePointer,
- 4, // eInt32,
- 8, // eInt64,
- 8, // eLong,
- 4, // eBool,
- }};
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
+ for (size_t i = 0; i < num_args; ++i) {
+ ArgItem &arg = arg_list[i];
+ // advance up the stack by one argument
+ sp += sizeof(uint32_t);
+ // get the argument type size
+ size_t arg_size = sizeof(uint32_t);
+ // read the argument from memory
+ arg.value = 0;
Error error;
+ size_t read =
+ ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), error);
+ if (read != arg_size || !error.Success()) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 " '%s'",
+ __FUNCTION__, uint64_t(i), error.AsCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 6;
+ // register passing order
+ static const std::array<const char *, c_args_in_reg> c_reg_names{
+ {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
+ // argument type to size mapping
+ static const std::array<size_t, 5> arg_size{{
+ 8, // ePointer,
+ 4, // eInt32,
+ 8, // eInt64,
+ 8, // eLong,
+ 4, // eBool,
+ }};
+
+ Error error;
+
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
+ // step over the return address
+ sp += sizeof(uint64_t);
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
- // step over the return address
- sp += sizeof(uint64_t);
-
- // check the stack alignment was correct (16 byte aligned)
- if ((sp & 0xf) != 0x0)
- {
- if (log)
- log->Printf("%s - stack misaligned", __FUNCTION__);
- return false;
- }
-
- // find the start of arguments on the stack
- uint64_t sp_offset = 0;
- for (uint32_t i = c_args_in_reg; i < num_args; ++i)
- {
- sp_offset += arg_size[arg_list[i].type];
- }
- // round up to multiple of 16
- sp_offset = (sp_offset + 0xf) & 0xf;
- sp += sp_offset;
-
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoByName(c_reg_names[i]);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t size = arg_size[arg_list[i].type];
- // read the argument from memory
- arg.value = 0;
- // note: due to little endian layout reading 4 or 8 bytes will give the correct value.
- size_t read = ctx.process->ReadMemory(sp, &arg.value, size, error);
- success = (error.Success() && read==size);
- // advance past this argument
- sp -= size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
- }
- return true;
-}
-
-bool
-GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 4;
-
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ // check the stack alignment was correct (16 byte aligned)
+ if ((sp & 0xf) != 0x0) {
+ if (log)
+ log->Printf("%s - stack misaligned", __FUNCTION__);
+ return false;
+ }
- Error error;
+ // find the start of arguments on the stack
+ uint64_t sp_offset = 0;
+ for (uint32_t i = c_args_in_reg; i < num_args; ++i) {
+ sp_offset += arg_size[arg_list[i].type];
+ }
+ // round up to multiple of 16
+ sp_offset = (sp_offset + 0xf) & 0xf;
+ sp += sp_offset;
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoByName(c_reg_names[i]);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
+ }
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t size = arg_size[arg_list[i].type];
+ // read the argument from memory
+ arg.value = 0;
+ // note: due to little endian layout reading 4 or 8 bytes will give the
+ // correct value.
+ size_t read = ctx.process->ReadMemory(sp, &arg.value, size, error);
+ success = (error.Success() && read == size);
+ // advance past this argument
+ sp -= size;
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 4;
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt32(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t arg_size = sizeof(uint32_t);
- // clear all 64bits
- arg.value = 0;
- // read this argument from memory
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += sizeof(uint32_t);
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
- }
- return true;
-}
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-bool
-GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 8;
+ Error error;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- if (log)
- log->Printf("%s - reading arguments spilled to stack not implemented", __FUNCTION__);
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__,
- uint64_t(i));
- return false;
- }
- }
- return true;
-}
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt32(0, &success);
+ }
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t arg_size = sizeof(uint32_t);
+ // clear all 64bits
+ arg.value = 0;
+ // read this argument from memory
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += sizeof(uint32_t);
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 8;
-bool
-GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 4;
- // register file offset to first argument
- static const uint32_t c_reg_offset = 4;
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
+ }
+ // arguments passed on the stack
+ else {
+ if (log)
+ log->Printf("%s - reading arguments spilled to stack not implemented",
+ __FUNCTION__);
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__,
+ uint64_t(i));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 4;
+ // register file offset to first argument
+ static const uint32_t c_reg_offset = 4;
- Error error;
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
- uint64_t sp = ctx.reg_ctx->GetSP() + 16;
+ Error error;
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- const size_t arg_size = sizeof(uint32_t);
- arg.value = 0;
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += arg_size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
- }
- return true;
-}
+ // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
+ uint64_t sp = ctx.reg_ctx->GetSP() + 16;
-bool
-GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 8;
- // register file offset to first argument
- static const uint32_t c_reg_offset = 4;
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
+ }
+ // arguments passed on the stack
+ else {
+ const size_t arg_size = sizeof(uint32_t);
+ arg.value = 0;
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += arg_size;
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 8;
+ // register file offset to first argument
+ static const uint32_t c_reg_offset = 4;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- Error error;
+ Error error;
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t arg_size = sizeof(uint64_t);
- // clear all 64bits
- arg.value = 0;
- // read this argument from memory
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += arg_size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
- }
- return true;
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
+ }
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t arg_size = sizeof(uint64_t);
+ // clear all 64bits
+ arg.value = 0;
+ // read this argument from memory
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += arg_size;
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
}
-bool
-GetArgs(ExecutionContext &context, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+bool GetArgs(ExecutionContext &context, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- // verify that we have a target
- if (!context.GetTargetPtr())
- {
- if (log)
- log->Printf("%s - invalid target", __FUNCTION__);
- return false;
- }
+ // verify that we have a target
+ if (!context.GetTargetPtr()) {
+ if (log)
+ log->Printf("%s - invalid target", __FUNCTION__);
+ return false;
+ }
- GetArgsCtx ctx = {context.GetRegisterContext(), context.GetProcessPtr()};
- assert(ctx.reg_ctx && ctx.process);
+ GetArgsCtx ctx = {context.GetRegisterContext(), context.GetProcessPtr()};
+ assert(ctx.reg_ctx && ctx.process);
- // dispatch based on architecture
- switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
- {
- case llvm::Triple::ArchType::x86:
- return GetArgsX86(ctx, arg_list, num_args);
+ // dispatch based on architecture
+ switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) {
+ case llvm::Triple::ArchType::x86:
+ return GetArgsX86(ctx, arg_list, num_args);
- case llvm::Triple::ArchType::x86_64:
- return GetArgsX86_64(ctx, arg_list, num_args);
+ case llvm::Triple::ArchType::x86_64:
+ return GetArgsX86_64(ctx, arg_list, num_args);
- case llvm::Triple::ArchType::arm:
- return GetArgsArm(ctx, arg_list, num_args);
+ case llvm::Triple::ArchType::arm:
+ return GetArgsArm(ctx, arg_list, num_args);
- case llvm::Triple::ArchType::aarch64:
- return GetArgsAarch64(ctx, arg_list, num_args);
+ case llvm::Triple::ArchType::aarch64:
+ return GetArgsAarch64(ctx, arg_list, num_args);
- case llvm::Triple::ArchType::mipsel:
- return GetArgsMipsel(ctx, arg_list, num_args);
+ case llvm::Triple::ArchType::mipsel:
+ return GetArgsMipsel(ctx, arg_list, num_args);
- case llvm::Triple::ArchType::mips64el:
- return GetArgsMips64el(ctx, arg_list, num_args);
+ case llvm::Triple::ArchType::mips64el:
+ return GetArgsMips64el(ctx, arg_list, num_args);
- default:
- // unsupported architecture
- if (log)
- {
- log->Printf("%s - architecture not supported: '%s'", __FUNCTION__,
- context.GetTargetRef().GetArchitecture().GetArchitectureName());
- }
- return false;
+ default:
+ // unsupported architecture
+ if (log) {
+ log->Printf(
+ "%s - architecture not supported: '%s'", __FUNCTION__,
+ context.GetTargetRef().GetArchitecture().GetArchitectureName());
}
+ return false;
+ }
}
} // anonymous namespace
-// The ScriptDetails class collects data associated with a single script instance.
-struct RenderScriptRuntime::ScriptDetails
-{
- ~ScriptDetails() = default;
-
- enum ScriptType
- {
- eScript,
- eScriptC
- };
-
- // The derived type of the script.
- empirical_type<ScriptType> type;
- // The name of the original source file.
- empirical_type<std::string> resName;
- // Path to script .so file on the device.
- empirical_type<std::string> scriptDyLib;
- // Directory where kernel objects are cached on device.
- empirical_type<std::string> cacheDir;
- // Pointer to the context which owns this script.
- empirical_type<lldb::addr_t> context;
- // Pointer to the script object itself.
- empirical_type<lldb::addr_t> script;
+// The ScriptDetails class collects data associated with a single script
+// instance.
+struct RenderScriptRuntime::ScriptDetails {
+ ~ScriptDetails() = default;
+
+ enum ScriptType { eScript, eScriptC };
+
+ // The derived type of the script.
+ empirical_type<ScriptType> type;
+ // The name of the original source file.
+ empirical_type<std::string> resName;
+ // Path to script .so file on the device.
+ empirical_type<std::string> scriptDyLib;
+ // Directory where kernel objects are cached on device.
+ empirical_type<std::string> cacheDir;
+ // Pointer to the context which owns this script.
+ empirical_type<lldb::addr_t> context;
+ // Pointer to the script object itself.
+ empirical_type<lldb::addr_t> script;
};
// This Element class represents the Element object in RS,
// defining the type associated with an Allocation.
-struct RenderScriptRuntime::Element
-{
- // Taken from rsDefines.h
- enum DataKind
- {
- RS_KIND_USER,
- RS_KIND_PIXEL_L = 7,
- RS_KIND_PIXEL_A,
- RS_KIND_PIXEL_LA,
- RS_KIND_PIXEL_RGB,
- RS_KIND_PIXEL_RGBA,
- RS_KIND_PIXEL_DEPTH,
- RS_KIND_PIXEL_YUV,
- RS_KIND_INVALID = 100
- };
-
- // Taken from rsDefines.h
- enum DataType
- {
- RS_TYPE_NONE = 0,
- RS_TYPE_FLOAT_16,
- RS_TYPE_FLOAT_32,
- RS_TYPE_FLOAT_64,
- RS_TYPE_SIGNED_8,
- RS_TYPE_SIGNED_16,
- RS_TYPE_SIGNED_32,
- RS_TYPE_SIGNED_64,
- RS_TYPE_UNSIGNED_8,
- RS_TYPE_UNSIGNED_16,
- RS_TYPE_UNSIGNED_32,
- RS_TYPE_UNSIGNED_64,
- RS_TYPE_BOOLEAN,
-
- RS_TYPE_UNSIGNED_5_6_5,
- RS_TYPE_UNSIGNED_5_5_5_1,
- RS_TYPE_UNSIGNED_4_4_4_4,
-
- RS_TYPE_MATRIX_4X4,
- RS_TYPE_MATRIX_3X3,
- RS_TYPE_MATRIX_2X2,
-
- RS_TYPE_ELEMENT = 1000,
- RS_TYPE_TYPE,
- RS_TYPE_ALLOCATION,
- RS_TYPE_SAMPLER,
- RS_TYPE_SCRIPT,
- RS_TYPE_MESH,
- RS_TYPE_PROGRAM_FRAGMENT,
- RS_TYPE_PROGRAM_VERTEX,
- RS_TYPE_PROGRAM_RASTER,
- RS_TYPE_PROGRAM_STORE,
- RS_TYPE_FONT,
-
- RS_TYPE_INVALID = 10000
- };
-
- std::vector<Element> children; // Child Element fields for structs
- empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
- empirical_type<DataType> type; // Type of each data pointer stored by the allocation
- empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image
- empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4
- empirical_type<uint32_t> field_count; // Number of Subelements
- empirical_type<uint32_t> datum_size; // Size of a single Element with padding
- empirical_type<uint32_t> padding; // Number of padding bytes
- empirical_type<uint32_t> array_size; // Number of items in array, only needed for strucrs
- ConstString type_name; // Name of type, only needed for structs
-
- static const ConstString &
- GetFallbackStructName(); // Print this as the type name of a struct Element
- // If we can't resolve the actual struct name
-
- bool
- shouldRefresh() const
- {
- const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
- const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid();
- return !valid_ptr || !valid_type || !datum_size.isValid();
- }
+struct RenderScriptRuntime::Element {
+ // Taken from rsDefines.h
+ enum DataKind {
+ RS_KIND_USER,
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+ RS_KIND_PIXEL_YUV,
+ RS_KIND_INVALID = 100
+ };
+
+ // Taken from rsDefines.h
+ enum DataType {
+ RS_TYPE_NONE = 0,
+ RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+ RS_TYPE_BOOLEAN,
+
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
+
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+ RS_TYPE_FONT,
+
+ RS_TYPE_INVALID = 10000
+ };
+
+ std::vector<Element> children; // Child Element fields for structs
+ empirical_type<lldb::addr_t>
+ element_ptr; // Pointer to the RS Element of the Type
+ empirical_type<DataType>
+ type; // Type of each data pointer stored by the allocation
+ empirical_type<DataKind>
+ type_kind; // Defines pixel type if Allocation is created from an image
+ empirical_type<uint32_t>
+ type_vec_size; // Vector size of each data point, e.g '4' for uchar4
+ empirical_type<uint32_t> field_count; // Number of Subelements
+ empirical_type<uint32_t> datum_size; // Size of a single Element with padding
+ empirical_type<uint32_t> padding; // Number of padding bytes
+ empirical_type<uint32_t>
+ array_size; // Number of items in array, only needed for strucrs
+ ConstString type_name; // Name of type, only needed for structs
+
+ static const ConstString &
+ GetFallbackStructName(); // Print this as the type name of a struct Element
+ // If we can't resolve the actual struct name
+
+ bool shouldRefresh() const {
+ const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
+ const bool valid_type =
+ type.isValid() && type_vec_size.isValid() && type_kind.isValid();
+ return !valid_ptr || !valid_type || !datum_size.isValid();
+ }
};
// This AllocationDetails class collects data associated with a single
// allocation instance.
-struct RenderScriptRuntime::AllocationDetails
-{
- struct Dimension
- {
- uint32_t dim_1;
- uint32_t dim_2;
- uint32_t dim_3;
- uint32_t cubeMap;
-
- Dimension()
- {
- dim_1 = 0;
- dim_2 = 0;
- dim_3 = 0;
- cubeMap = 0;
- }
- };
-
- // The FileHeader struct specifies the header we use for writing allocations to a binary file.
- // Our format begins with the ASCII characters "RSAD", identifying the file as an allocation dump.
- // Member variables dims and hdr_size are then written consecutively, immediately followed by an instance of
- // the ElementHeader struct. Because Elements can contain subelements, there may be more than one instance
- // of the ElementHeader struct. With this first instance being the root element, and the other instances being
- // the root's descendants. To identify which instances are an ElementHeader's children, each struct
- // is immediately followed by a sequence of consecutive offsets to the start of its child structs.
- // These offsets are 4 bytes in size, and the 0 offset signifies no more children.
- struct FileHeader
- {
- uint8_t ident[4]; // ASCII 'RSAD' identifying the file
- uint32_t dims[3]; // Dimensions
- uint16_t hdr_size; // Header size in bytes, including all element headers
- };
-
- struct ElementHeader
- {
- uint16_t type; // DataType enum
- uint32_t kind; // DataKind enum
- uint32_t element_size; // Size of a single element, including padding
- uint16_t vector_size; // Vector width
- uint32_t array_size; // Number of elements in array
- };
-
- // Monotonically increasing from 1
- static uint32_t ID;
-
- // Maps Allocation DataType enum and vector size to printable strings
- // using mapping from RenderScript numerical types summary documentation
- static const char *RsDataTypeToString[][4];
-
- // Maps Allocation DataKind enum to printable strings
- static const char *RsDataKindToString[];
-
- // Maps allocation types to format sizes for printing.
- static const uint32_t RSTypeToFormat[][3];
-
- // Give each allocation an ID as a way
- // for commands to reference it.
- const uint32_t id;
-
- RenderScriptRuntime::Element element; // Allocation Element type
- empirical_type<Dimension> dimension; // Dimensions of the Allocation
- empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation
- empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation
- empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation
- empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation
- empirical_type<uint32_t> size; // Size of the allocation
- empirical_type<uint32_t> stride; // Stride between rows of the allocation
-
- // Give each allocation an id, so we can reference it in user commands.
- AllocationDetails() : id(ID++) {}
-
- bool
- shouldRefresh() const
- {
- bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
- valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
- return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh();
- }
+struct RenderScriptRuntime::AllocationDetails {
+ struct Dimension {
+ uint32_t dim_1;
+ uint32_t dim_2;
+ uint32_t dim_3;
+ uint32_t cubeMap;
+
+ Dimension() {
+ dim_1 = 0;
+ dim_2 = 0;
+ dim_3 = 0;
+ cubeMap = 0;
+ }
+ };
+
+ // The FileHeader struct specifies the header we use for writing allocations
+ // to a binary file.
+ // Our format begins with the ASCII characters "RSAD", identifying the file as
+ // an allocation dump.
+ // Member variables dims and hdr_size are then written consecutively,
+ // immediately followed by an instance of
+ // the ElementHeader struct. Because Elements can contain subelements, there
+ // may be more than one instance
+ // of the ElementHeader struct. With this first instance being the root
+ // element, and the other instances being
+ // the root's descendants. To identify which instances are an ElementHeader's
+ // children, each struct
+ // is immediately followed by a sequence of consecutive offsets to the start
+ // of its child structs.
+ // These offsets are 4 bytes in size, and the 0 offset signifies no more
+ // children.
+ struct FileHeader {
+ uint8_t ident[4]; // ASCII 'RSAD' identifying the file
+ uint32_t dims[3]; // Dimensions
+ uint16_t hdr_size; // Header size in bytes, including all element headers
+ };
+
+ struct ElementHeader {
+ uint16_t type; // DataType enum
+ uint32_t kind; // DataKind enum
+ uint32_t element_size; // Size of a single element, including padding
+ uint16_t vector_size; // Vector width
+ uint32_t array_size; // Number of elements in array
+ };
+
+ // Monotonically increasing from 1
+ static uint32_t ID;
+
+ // Maps Allocation DataType enum and vector size to printable strings
+ // using mapping from RenderScript numerical types summary documentation
+ static const char *RsDataTypeToString[][4];
+
+ // Maps Allocation DataKind enum to printable strings
+ static const char *RsDataKindToString[];
+
+ // Maps allocation types to format sizes for printing.
+ static const uint32_t RSTypeToFormat[][3];
+
+ // Give each allocation an ID as a way
+ // for commands to reference it.
+ const uint32_t id;
+
+ RenderScriptRuntime::Element element; // Allocation Element type
+ empirical_type<Dimension> dimension; // Dimensions of the Allocation
+ empirical_type<lldb::addr_t>
+ address; // Pointer to address of the RS Allocation
+ empirical_type<lldb::addr_t>
+ data_ptr; // Pointer to the data held by the Allocation
+ empirical_type<lldb::addr_t>
+ type_ptr; // Pointer to the RS Type of the Allocation
+ empirical_type<lldb::addr_t>
+ context; // Pointer to the RS Context of the Allocation
+ empirical_type<uint32_t> size; // Size of the allocation
+ empirical_type<uint32_t> stride; // Stride between rows of the allocation
+
+ // Give each allocation an id, so we can reference it in user commands.
+ AllocationDetails() : id(ID++) {}
+
+ bool shouldRefresh() const {
+ bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
+ valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
+ return !valid_ptrs || !dimension.isValid() || !size.isValid() ||
+ element.shouldRefresh();
+ }
};
-const ConstString &
-RenderScriptRuntime::Element::GetFallbackStructName()
-{
- static const ConstString FallbackStructName("struct");
- return FallbackStructName;
+const ConstString &RenderScriptRuntime::Element::GetFallbackStructName() {
+ static const ConstString FallbackStructName("struct");
+ return FallbackStructName;
}
uint32_t RenderScriptRuntime::AllocationDetails::ID = 1;
const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = {
- "User",
- "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
+ "User", "Undefined", "Undefined", "Undefined",
+ "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
"L Pixel", "A Pixel", "LA Pixel", "RGB Pixel",
"RGBA Pixel", "Pixel Depth", "YUV Pixel"};
@@ -720,54 +664,64 @@ const char *RenderScriptRuntime::Allocat
// Deprecated
{"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
- {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"},
- {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"},
- {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"},
- {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"},
+ {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment",
+ "RS Program Fragment"},
+ {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex",
+ "RS Program Vertex"},
+ {"RS Program Raster", "RS Program Raster", "RS Program Raster",
+ "RS Program Raster"},
+ {"RS Program Store", "RS Program Store", "RS Program Store",
+ "RS Program Store"},
{"RS Font", "RS Font", "RS Font", "RS Font"}};
// Used as an index into the RSTypeToFormat array elements
-enum TypeToFormatIndex
-{
- eFormatSingle = 0,
- eFormatVector,
- eElementSize
-};
+enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize };
-// { format enum of single element, format enum of element vector, size of element}
+// { format enum of single element, format enum of element vector, size of
+// element}
const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = {
- {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
- {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
- {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
- {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
- {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
- {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
- {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
- {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
- {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
- {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
- {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
- {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
- {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
+ {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
+ {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
+ {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
+ {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
+ {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
+ {eFormatDecimal, eFormatVectorOfSInt16,
+ sizeof(int16_t)}, // RS_TYPE_SIGNED_16
+ {eFormatDecimal, eFormatVectorOfSInt32,
+ sizeof(int32_t)}, // RS_TYPE_SIGNED_32
+ {eFormatDecimal, eFormatVectorOfSInt64,
+ sizeof(int64_t)}, // RS_TYPE_SIGNED_64
+ {eFormatDecimal, eFormatVectorOfUInt8,
+ sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
+ {eFormatDecimal, eFormatVectorOfUInt16,
+ sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
+ {eFormatDecimal, eFormatVectorOfUInt32,
+ sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
+ {eFormatDecimal, eFormatVectorOfUInt64,
+ sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
+ {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
};
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
-RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
-{
+RenderScriptRuntime::CreateInstance(Process *process,
+ lldb::LanguageType language) {
- if (language == eLanguageTypeExtRenderScript)
- return new RenderScriptRuntime(process);
- else
- return nullptr;
+ if (language == eLanguageTypeExtRenderScript)
+ return new RenderScriptRuntime(process);
+ else
+ return nullptr;
}
// Callback with a module to search for matching symbols.
@@ -775,1896 +729,1862 @@ RenderScriptRuntime::CreateInstance(Proc
// Then look for a symbol which matches our kernel name.
// The breakpoint address is finally set using the address of this symbol.
Searcher::CallbackReturn
-RSBreakpointResolver::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *, bool)
-{
- ModuleSP module = context.module_sp;
-
- if (!module)
- return Searcher::eCallbackReturnContinue;
-
- // Is this a module containing renderscript kernels?
- if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
- return Searcher::eCallbackReturnContinue;
-
- // Attempt to set a breakpoint on the kernel name symbol within the module library.
- // If it's not found, it's likely debug info is unavailable - try to set a
- // breakpoint on <name>.expand.
-
- const Symbol *kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
- if (!kernel_sym)
- {
- std::string kernel_name_expanded(m_kernel_name.AsCString());
- kernel_name_expanded.append(".expand");
- kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
- }
+RSBreakpointResolver::SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *, bool) {
+ ModuleSP module = context.module_sp;
- if (kernel_sym)
- {
- Address bp_addr = kernel_sym->GetAddress();
- if (filter.AddressPasses(bp_addr))
- m_breakpoint->AddLocation(bp_addr);
- }
+ if (!module)
+ return Searcher::eCallbackReturnContinue;
+ // Is this a module containing renderscript kernels?
+ if (nullptr ==
+ module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"),
+ eSymbolTypeData))
return Searcher::eCallbackReturnContinue;
-}
-void
-RenderScriptRuntime::Initialize()
-{
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance,
- GetCommandObject);
-}
-
-void
-RenderScriptRuntime::Terminate()
-{
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString
-RenderScriptRuntime::GetPluginNameStatic()
-{
- static ConstString g_name("renderscript");
- return g_name;
+ // Attempt to set a breakpoint on the kernel name symbol within the module
+ // library.
+ // If it's not found, it's likely debug info is unavailable - try to set a
+ // breakpoint on <name>.expand.
+
+ const Symbol *kernel_sym =
+ module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
+ if (!kernel_sym) {
+ std::string kernel_name_expanded(m_kernel_name.AsCString());
+ kernel_name_expanded.append(".expand");
+ kernel_sym = module->FindFirstSymbolWithNameAndType(
+ ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ }
+
+ if (kernel_sym) {
+ Address bp_addr = kernel_sym->GetAddress();
+ if (filter.AddressPasses(bp_addr))
+ m_breakpoint->AddLocation(bp_addr);
+ }
+
+ return Searcher::eCallbackReturnContinue;
+}
+
+void RenderScriptRuntime::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "RenderScript language support", CreateInstance,
+ GetCommandObject);
+}
+
+void RenderScriptRuntime::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString RenderScriptRuntime::GetPluginNameStatic() {
+ static ConstString g_name("renderscript");
+ return g_name;
}
RenderScriptRuntime::ModuleKind
-RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
-{
- if (module_sp)
- {
- // Is this a module containing renderscript kernels?
- const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
- if (info_sym)
- {
- return eModuleKindKernelObj;
- }
+RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) {
+ if (module_sp) {
+ // Is this a module containing renderscript kernels?
+ const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(
+ ConstString(".rs.info"), eSymbolTypeData);
+ if (info_sym) {
+ return eModuleKindKernelObj;
+ }
- // Is this the main RS runtime library
- const ConstString rs_lib("libRS.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_lib)
- {
- return eModuleKindLibRS;
- }
+ // Is this the main RS runtime library
+ const ConstString rs_lib("libRS.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_lib) {
+ return eModuleKindLibRS;
+ }
- const ConstString rs_driverlib("libRSDriver.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
- {
- return eModuleKindDriver;
- }
+ const ConstString rs_driverlib("libRSDriver.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) {
+ return eModuleKindDriver;
+ }
- const ConstString rs_cpureflib("libRSCpuRef.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
- {
- return eModuleKindImpl;
- }
+ const ConstString rs_cpureflib("libRSCpuRef.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) {
+ return eModuleKindImpl;
}
- return eModuleKindIgnored;
+ }
+ return eModuleKindIgnored;
}
-bool
-RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
-{
- return GetModuleKind(module_sp) != eModuleKindIgnored;
+bool RenderScriptRuntime::IsRenderScriptModule(
+ const lldb::ModuleSP &module_sp) {
+ return GetModuleKind(module_sp) != eModuleKindIgnored;
}
-void
-RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list)
-{
- std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
+void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) {
+ std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
- size_t num_modules = module_list.GetSize();
- for (size_t i = 0; i < num_modules; i++)
- {
- auto mod = module_list.GetModuleAtIndex(i);
- if (IsRenderScriptModule(mod))
- {
- LoadModule(mod);
- }
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++) {
+ auto mod = module_list.GetModuleAtIndex(i);
+ if (IsRenderScriptModule(mod)) {
+ LoadModule(mod);
}
+ }
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-RenderScriptRuntime::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString RenderScriptRuntime::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-RenderScriptRuntime::GetPluginVersion()
-{
- return 1;
-}
+uint32_t RenderScriptRuntime::GetPluginVersion() { return 1; }
-bool
-RenderScriptRuntime::IsVTableName(const char *name)
-{
- return false;
-}
+bool RenderScriptRuntime::IsVTableName(const char *name) { return false; }
-bool
-RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type)
-{
- return false;
+bool RenderScriptRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ return false;
}
TypeAndOrName
-RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
-{
- return type_and_or_name;
+RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) {
+ return type_and_or_name;
}
-bool
-RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
-{
- return false;
+bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ return false;
}
lldb::BreakpointResolverSP
-RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
-{
- BreakpointResolverSP resolver_sp;
- return resolver_sp;
-}
-
-const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = {
- // rsdScript
- {
- "rsdScriptInit",
- "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj",
- "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureScriptInit
- },
- {
- "rsdScriptInvokeForEachMulti",
- "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
- "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti
- },
- {
- "rsdScriptSetGlobalVar",
- "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj",
- "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar
- },
-
- // rsdAllocation
- {
- "rsdAllocationInit",
- "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb",
- "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureAllocationInit
- },
- {
- "rsdAllocationRead2D",
- "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
- "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- nullptr
- },
- {
- "rsdAllocationDestroy",
- "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE",
- "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy
- },
+RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
+ bool throw_bp) {
+ BreakpointResolverSP resolver_sp;
+ return resolver_sp;
+}
+
+const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
+ {
+ // rsdScript
+ {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP"
+ "NS0_7ScriptCEPKcS7_PKhjj",
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_"
+ "7ScriptCEPKcS7_PKhmj",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureScriptInit},
+ {"rsdScriptInvokeForEachMulti",
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
+ "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
+ "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti},
+ {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render"
+ "script7ContextEPKNS0_6ScriptEjPvj",
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_"
+ "6ScriptEjPvm",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar},
+
+ // rsdAllocation
+ {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C"
+ "ontextEPNS0_10AllocationEb",
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_"
+ "10AllocationEb",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureAllocationInit},
+ {"rsdAllocationRead2D",
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
+ "10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
+ "10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
+ 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc"
+ "ript7ContextEPNS0_10AllocationE",
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_"
+ "10AllocationE",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},
};
-const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
-
-bool
-RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id)
-{
- RuntimeHook *hook_info = (RuntimeHook *)baton;
- ExecutionContext context(ctx->exe_ctx_ref);
+const size_t RenderScriptRuntime::s_runtimeHookCount =
+ sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
- RenderScriptRuntime *lang_rt =
- (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+bool RenderScriptRuntime::HookCallback(void *baton,
+ StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id) {
+ RuntimeHook *hook_info = (RuntimeHook *)baton;
+ ExecutionContext context(ctx->exe_ctx_ref);
+
+ RenderScriptRuntime *lang_rt =
+ (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+
+ lang_rt->HookCallback(hook_info, context);
+
+ return false;
+}
+
+void RenderScriptRuntime::HookCallback(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (log)
+ log->Printf("%s - '%s'", __FUNCTION__, hook_info->defn->name);
+
+ if (hook_info->defn->grabber) {
+ (this->*(hook_info->defn->grabber))(hook_info, context);
+ }
+}
+
+void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
+ RuntimeHook *hook_info, ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum {
+ eRsContext = 0,
+ eRsScript,
+ eRsSlot,
+ eRsAIns,
+ eRsInLen,
+ eRsAOut,
+ eRsUsr,
+ eRsUsrLen,
+ eRsSc,
+ };
+
+ std::array<ArgItem, 9> args{{
+ ArgItem{ArgItem::ePointer, 0}, // const Context *rsc
+ ArgItem{ArgItem::ePointer, 0}, // Script *s
+ ArgItem{ArgItem::eInt32, 0}, // uint32_t slot
+ ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns
+ ArgItem{ArgItem::eInt32, 0}, // size_t inLen
+ ArgItem{ArgItem::ePointer, 0}, // Allocation *aout
+ ArgItem{ArgItem::ePointer, 0}, // const void *usr
+ ArgItem{ArgItem::eInt32, 0}, // size_t usrLen
+ ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc
+ }};
- lang_rt->HookCallback(hook_info, context);
-
- return false;
-}
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - Error while reading the function parameters",
+ __FUNCTION__);
+ return;
+ }
+
+ const uint32_t target_ptr_size = m_process->GetAddressByteSize();
+ Error error;
+ std::vector<uint64_t> allocs;
+
+ // traverse allocation list
+ for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) {
+ // calculate offest to allocation pointer
+ const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;
+
+ // Note: due to little endian layout, reading 32bits or 64bits into res64
+ // will
+ // give the correct results.
+
+ uint64_t res64 = 0;
+ size_t read = m_process->ReadMemory(addr, &res64, target_ptr_size, error);
+ if (read != target_ptr_size || !error.Success()) {
+ if (log)
+ log->Printf(
+ "%s - Error while reading allocation list argument %" PRIu64,
+ __FUNCTION__, i);
+ } else {
+ allocs.push_back(res64);
+ }
+ }
+
+ // if there is an output allocation track it
+ if (uint64_t aOut = uint64_t(args[eRsAOut])) {
+ allocs.push_back(aOut);
+ }
+
+ // for all allocations we have found
+ for (const uint64_t alloc_addr : allocs) {
+ AllocationDetails *alloc = LookUpAllocation(alloc_addr);
+ if (!alloc)
+ alloc = CreateAllocation(alloc_addr);
-void
-RenderScriptRuntime::HookCallback(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (alloc) {
+ // save the allocation address
+ if (alloc->address.isValid()) {
+ // check the allocation address we already have matches
+ assert(*alloc->address.get() == alloc_addr);
+ } else {
+ alloc->address = alloc_addr;
+ }
+
+ // save the context
+ if (log) {
+ if (alloc->context.isValid() &&
+ *alloc->context.get() != addr_t(args[eRsContext]))
+ log->Printf("%s - Allocation used by multiple contexts",
+ __FUNCTION__);
+ }
+ alloc->context = addr_t(args[eRsContext]);
+ }
+ }
+
+ // make sure we track this script object
+ if (lldb_private::RenderScriptRuntime::ScriptDetails *script =
+ LookUpScript(addr_t(args[eRsScript]), true)) {
+ if (log) {
+ if (script->context.isValid() &&
+ *script->context.get() != addr_t(args[eRsContext]))
+ log->Printf("%s - Script used by multiple contexts", __FUNCTION__);
+ }
+ script->context = addr_t(args[eRsContext]);
+ }
+}
+
+void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum {
+ eRsContext,
+ eRsScript,
+ eRsId,
+ eRsData,
+ eRsLength,
+ };
+
+ std::array<ArgItem, 5> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsScript
+ ArgItem{ArgItem::eInt32, 0}, // eRsId
+ ArgItem{ArgItem::ePointer, 0}, // eRsData
+ ArgItem{ArgItem::eInt32, 0}, // eRsLength
+ }};
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading the function parameters.", __FUNCTION__);
+ return;
+ }
+
+ if (log) {
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64
+ ":%" PRIu64 "bytes.",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
+ uint64_t(args[eRsData]), uint64_t(args[eRsLength]));
+
+ addr_t script_addr = addr_t(args[eRsScript]);
+ if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) {
+ auto rsm = m_scriptMappings[script_addr];
+ if (uint64_t(args[eRsId]) < rsm->m_globals.size()) {
+ auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
+ log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__,
+ rsg.m_name.AsCString(),
+ rsm->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ }
+}
+
+void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum { eRsContext, eRsAlloc, eRsForceZero };
+
+ std::array<ArgItem, 3> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
+ ArgItem{ArgItem::eBool, 0}, // eRsForceZero
+ }};
+
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) // error case
+ {
if (log)
- log->Printf("%s - '%s'", __FUNCTION__, hook_info->defn->name);
+ log->Printf("%s - error while reading the function parameters",
+ __FUNCTION__);
+ return; // abort
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero]));
+
+ AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
+ if (alloc)
+ alloc->context = uint64_t(args[eRsContext]);
+}
+
+void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum {
+ eRsContext,
+ eRsAlloc,
+ };
+
+ std::array<ArgItem, 2> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
+ }};
- if (hook_info->defn->grabber)
- {
- (this->*(hook_info->defn->grabber))(hook_info, context);
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error while reading the function parameters.",
+ __FUNCTION__);
+ return;
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__,
+ uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]));
+
+ for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) {
+ auto &allocation_ap = *iter; // get the unique pointer
+ if (allocation_ap->address.isValid() &&
+ *allocation_ap->address.get() == addr_t(args[eRsAlloc])) {
+ m_allocations.erase(iter);
+ if (log)
+ log->Printf("%s - deleted allocation entry.", __FUNCTION__);
+ return;
+ }
+ }
+
+ if (log)
+ log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__);
+}
+
+void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ Error error;
+ Process *process = context.GetProcessPtr();
+
+ enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr };
+
+ std::array<ArgItem, 4> args{
+ {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
+ ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error while reading the function parameters.",
+ __FUNCTION__);
+ return;
+ }
+
+ std::string resname;
+ process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), resname, error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - error reading resname: %s.", __FUNCTION__,
+ error.AsCString());
+ }
+
+ std::string cachedir;
+ process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cachedir,
+ error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - error reading cachedir: %s.", __FUNCTION__,
+ error.AsCString());
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]), resname.c_str(), cachedir.c_str());
+
+ if (resname.size() > 0) {
+ StreamString strm;
+ strm.Printf("librs.%s.so", resname.c_str());
+
+ ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
+ if (script) {
+ script->type = ScriptDetails::eScriptC;
+ script->cacheDir = cachedir;
+ script->resName = resname;
+ script->scriptDyLib = strm.GetData();
+ script->context = addr_t(args[eRsContext]);
}
-}
-void
-RenderScriptRuntime::CaptureScriptInvokeForEachMulti(RuntimeHook* hook_info,
- ExecutionContext& context)
-{
- Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- enum
- {
- eRsContext = 0,
- eRsScript,
- eRsSlot,
- eRsAIns,
- eRsInLen,
- eRsAOut,
- eRsUsr,
- eRsUsrLen,
- eRsSc,
- };
-
- std::array<ArgItem, 9> args{{
- ArgItem{ArgItem::ePointer, 0}, // const Context *rsc
- ArgItem{ArgItem::ePointer, 0}, // Script *s
- ArgItem{ArgItem::eInt32, 0}, // uint32_t slot
- ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns
- ArgItem{ArgItem::eInt32, 0}, // size_t inLen
- ArgItem{ArgItem::ePointer, 0}, // Allocation *aout
- ArgItem{ArgItem::ePointer, 0}, // const void *usr
- ArgItem{ArgItem::eInt32, 0}, // size_t usrLen
- ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc
- }};
-
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - Error while reading the function parameters", __FUNCTION__);
- return;
- }
+ if (log)
+ log->Printf("%s - '%s' tagged with context 0x%" PRIx64
+ " and script 0x%" PRIx64 ".",
+ __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]));
+ } else if (log) {
+ log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__);
+ }
+}
+
+void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
+ ModuleKind kind) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!module) {
+ return;
+ }
+
+ Target &target = GetProcess()->GetTarget();
+ llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
+
+ if (targetArchType != llvm::Triple::ArchType::x86 &&
+ targetArchType != llvm::Triple::ArchType::arm &&
+ targetArchType != llvm::Triple::ArchType::aarch64 &&
+ targetArchType != llvm::Triple::ArchType::mipsel &&
+ targetArchType != llvm::Triple::ArchType::mips64el &&
+ targetArchType != llvm::Triple::ArchType::x86_64) {
+ if (log)
+ log->Printf("%s - unable to hook runtime functions.", __FUNCTION__);
+ return;
+ }
+
+ uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
+
+ for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
+ const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
+ if (hook_defn->kind != kind) {
+ continue;
+ }
+
+ const char *symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32
+ : hook_defn->symbol_name_m64;
+
+ const Symbol *sym = module->FindFirstSymbolWithNameAndType(
+ ConstString(symbol_name), eSymbolTypeCode);
+ if (!sym) {
+ if (log) {
+ log->Printf("%s - symbol '%s' related to the function %s not found",
+ __FUNCTION__, symbol_name, hook_defn->name);
+ }
+ continue;
+ }
+
+ addr_t addr = sym->GetLoadAddress(&target);
+ if (addr == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("%s - unable to resolve the address of hook function '%s' "
+ "with symbol '%s'.",
+ __FUNCTION__, hook_defn->name, symbol_name);
+ continue;
+ } else {
+ if (log)
+ log->Printf("%s - function %s, address resolved at 0x%" PRIx64,
+ __FUNCTION__, hook_defn->name, addr);
+ }
+
+ RuntimeHookSP hook(new RuntimeHook());
+ hook->address = addr;
+ hook->defn = hook_defn;
+ hook->bp_sp = target.CreateBreakpoint(addr, true, false);
+ hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
+ m_runtimeHooks[addr] = hook;
+ if (log) {
+ log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64
+ " at 0x%" PRIx64 ".",
+ __FUNCTION__, hook_defn->name,
+ module->GetFileSpec().GetFilename().AsCString(),
+ (uint64_t)hook_defn->version, (uint64_t)addr);
+ }
+ }
+}
+
+void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
+ if (!rsmodule_sp)
+ return;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ const ModuleSP module = rsmodule_sp->m_module;
+ const FileSpec &file = module->GetPlatformFileSpec();
+
+ // Iterate over all of the scripts that we currently know of.
+ // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ for (const auto &rs_script : m_scripts) {
+ // Extract the expected .so file path for this script.
+ std::string dylib;
+ if (!rs_script->scriptDyLib.get(dylib))
+ continue;
+
+ // Only proceed if the module that has loaded corresponds to this script.
+ if (file.GetFilename() != ConstString(dylib.c_str()))
+ continue;
+
+ // Obtain the script address which we use as a key.
+ lldb::addr_t script;
+ if (!rs_script->script.get(script))
+ continue;
+
+ // If we have a script mapping for the current script.
+ if (m_scriptMappings.find(script) != m_scriptMappings.end()) {
+ // if the module we have stored is different to the one we just received.
+ if (m_scriptMappings[script] != rsmodule_sp) {
+ if (log)
+ log->Printf(
+ "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+ __FUNCTION__, (uint64_t)script,
+ rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ // We don't have a script mapping for the current script.
+ else {
+ // Obtain the script resource name.
+ std::string resName;
+ if (rs_script->resName.get(resName))
+ // Set the modules resource name.
+ rsmodule_sp->m_resname = resName;
+ // Add Script/Module pair to map.
+ m_scriptMappings[script] = rsmodule_sp;
+ if (log)
+ log->Printf(
+ "%s - script %" PRIx64 " associated with rsmodule '%s'.",
+ __FUNCTION__, (uint64_t)script,
+ rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+}
+
+// Uses the Target API to evaluate the expression passed as a parameter to the
+// function
+// The result of that expression is returned an unsigned 64 bit int, via the
+// result* parameter.
+// Function returns true on success, and false on failure
+bool RenderScriptRuntime::EvalRSExpression(const char *expression,
+ StackFrame *frame_ptr,
+ uint64_t *result) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log)
+ log->Printf("%s(%s)", __FUNCTION__, expression);
+
+ ValueObjectSP expr_result;
+ EvaluateExpressionOptions options;
+ options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
+ // Perform the actual expression evaluation
+ GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr,
+ expr_result, options);
- const uint32_t target_ptr_size = m_process->GetAddressByteSize();
- Error error;
- std::vector<uint64_t> allocs;
+ if (!expr_result) {
+ if (log)
+ log->Printf("%s: couldn't evaluate expression.", __FUNCTION__);
+ return false;
+ }
- // traverse allocation list
- for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i)
+ // The result of the expression is invalid
+ if (!expr_result->GetError().Success()) {
+ Error err = expr_result->GetError();
+ if (err.GetError() == UserExpression::kNoResult) // Expression returned
+ // void, so this is
+ // actually a success
{
- // calculate offest to allocation pointer
- const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;
+ if (log)
+ log->Printf("%s - expression returned void.", __FUNCTION__);
- // Note: due to little endian layout, reading 32bits or 64bits into res64 will
- // give the correct results.
-
- uint64_t res64 = 0;
- size_t read = m_process->ReadMemory(addr, &res64, target_ptr_size, error);
- if (read != target_ptr_size || !error.Success())
- {
- if (log)
- log->Printf("%s - Error while reading allocation list argument %" PRIu64, __FUNCTION__, i);
- }
- else
- {
- allocs.push_back(res64);
- }
+ result = nullptr;
+ return true;
}
- // if there is an output allocation track it
- if (uint64_t aOut = uint64_t(args[eRsAOut]))
- {
- allocs.push_back(aOut);
- }
+ if (log)
+ log->Printf("%s - error evaluating expression result: %s", __FUNCTION__,
+ err.AsCString());
+ return false;
+ }
- // for all allocations we have found
- for (const uint64_t alloc_addr : allocs)
- {
- AllocationDetails *alloc = LookUpAllocation(alloc_addr);
- if (!alloc)
- alloc = CreateAllocation(alloc_addr);
-
- if (alloc)
- {
- // save the allocation address
- if (alloc->address.isValid())
- {
- // check the allocation address we already have matches
- assert(*alloc->address.get() == alloc_addr);
- }
- else
- {
- alloc->address = alloc_addr;
- }
+ bool success = false;
+ *result = expr_result->GetValueAsUnsigned(
+ 0, &success); // We only read the result as an uint32_t.
- // save the context
- if (log)
- {
- if (alloc->context.isValid() && *alloc->context.get() != addr_t(args[eRsContext]))
- log->Printf("%s - Allocation used by multiple contexts", __FUNCTION__);
- }
- alloc->context = addr_t(args[eRsContext]);
- }
- }
+ if (!success) {
+ if (log)
+ log->Printf("%s - couldn't convert expression result to uint32_t",
+ __FUNCTION__);
+ return false;
+ }
- // make sure we track this script object
- if (lldb_private::RenderScriptRuntime::ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true))
- {
- if (log)
- {
- if (script->context.isValid() && *script->context.get() != addr_t(args[eRsContext]))
- log->Printf("%s - Script used by multiple contexts", __FUNCTION__);
- }
- script->context = addr_t(args[eRsContext]);
- }
+ return true;
}
-void
-RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+namespace {
+// Used to index expression format strings
+enum ExpressionStrings {
+ eExprGetOffsetPtr = 0,
+ eExprAllocGetType,
+ eExprTypeDimX,
+ eExprTypeDimY,
+ eExprTypeDimZ,
+ eExprTypeElemPtr,
+ eExprElementType,
+ eExprElementKind,
+ eExprElementVec,
+ eExprElementFieldCount,
+ eExprSubelementsId,
+ eExprSubelementsName,
+ eExprSubelementsArrSize,
- enum
- {
- eRsContext,
- eRsScript,
- eRsId,
- eRsData,
- eRsLength,
- };
-
- std::array<ArgItem, 5> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsScript
- ArgItem{ArgItem::eInt32, 0}, // eRsId
- ArgItem{ArgItem::ePointer, 0}, // eRsData
- ArgItem{ArgItem::eInt32, 0}, // eRsLength
- }};
+ _eExprLast // keep at the end, implicit size of the array runtimeExpressions
+};
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading the function parameters.", __FUNCTION__);
- return;
- }
+// max length of an expanded expression
+const int jit_max_expr_size = 512;
- if (log)
- {
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", __FUNCTION__,
- uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
- uint64_t(args[eRsData]), uint64_t(args[eRsLength]));
-
- addr_t script_addr = addr_t(args[eRsScript]);
- if (m_scriptMappings.find(script_addr) != m_scriptMappings.end())
- {
- auto rsm = m_scriptMappings[script_addr];
- if (uint64_t(args[eRsId]) < rsm->m_globals.size())
- {
- auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
- log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__, rsg.m_name.AsCString(),
- rsm->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
- }
+// Retrieve the string to JIT for the given expression
+const char *JITTemplate(ExpressionStrings e) {
+ // Format strings containing the expressions we may need to evaluate.
+ static std::array<const char *, _eExprLast> runtimeExpressions = {
+ {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "(int*)_"
+ "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
+ "CubemapFace"
+ "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY;
+ // mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between
+ // devices
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[0]", // X dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[1]", // Y dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[2]", // Z dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[5]", // Element ptr
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
+ // elemData
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[0]", // Type
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[1]", // Kind
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[4]", // Field Count
+
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
+ // *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about
+ // fields/Subelements
+ // Element* of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]",
+
+ // Name of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]",
+
+ // Array size of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}};
+
+ return runtimeExpressions[e];
}
+} // end of the anonymous namespace
-void
-RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+// JITs the RS runtime for the internal data pointer of an allocation.
+// Is passed x,y,z coordinates for the pointer to a specific element.
+// Then sets the data_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool RenderScriptRuntime::JITDataPointer(AllocationDetails *allocation,
+ StackFrame *frame_ptr, uint32_t x,
+ uint32_t y, uint32_t z) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- enum
- {
- eRsContext,
- eRsAlloc,
- eRsForceZero
- };
-
- std::array<ArgItem, 3> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
- ArgItem{ArgItem::eBool, 0}, // eRsForceZero
- }};
+ if (!allocation->address.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- bool success = GetArgs(context, &args[0], args.size());
- if (!success) // error case
- {
- if (log)
- log->Printf("%s - error while reading the function parameters", __FUNCTION__);
- return; // abort
- }
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), x, y, z);
+ if (chars_written < 0) {
if (log)
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero]));
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
- if (alloc)
- alloc->context = uint64_t(args[eRsContext]);
-}
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
-void
-RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->data_ptr = mem_ptr;
- enum
- {
- eRsContext,
- eRsAlloc,
- };
-
- std::array<ArgItem, 2> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
- }};
+ return true;
+}
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - error while reading the function parameters.", __FUNCTION__);
- return;
- }
+// JITs the RS runtime for the internal pointer to the RS Type of an allocation
+// Then sets the type_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool RenderScriptRuntime::JITTypePointer(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (!allocation->address.isValid() || !allocation->context.isValid()) {
if (log)
- log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsAlloc]));
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter)
- {
- auto &allocation_ap = *iter; // get the unique pointer
- if (allocation_ap->address.isValid() && *allocation_ap->address.get() == addr_t(args[eRsAlloc]))
- {
- m_allocations.erase(iter);
- if (log)
- log->Printf("%s - deleted allocation entry.", __FUNCTION__);
- return;
- }
- }
+ const char *expr_cstr = JITTemplate(eExprAllocGetType);
+ char buffer[jit_max_expr_size];
+ int chars_written =
+ snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(),
+ *allocation->address.get());
+ if (chars_written < 0) {
if (log)
- log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__);
-}
-
-void
-RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- Error error;
- Process *process = context.GetProcessPtr();
-
- enum
- {
- eRsContext,
- eRsScript,
- eRsResNamePtr,
- eRsCachedDirPtr
- };
-
- std::array<ArgItem, 4> args{{ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
- ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - error while reading the function parameters.", __FUNCTION__);
- return;
- }
-
- std::string resname;
- process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), resname, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - error reading resname: %s.", __FUNCTION__, error.AsCString());
- }
-
- std::string cachedir;
- process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cachedir, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - error reading cachedir: %s.", __FUNCTION__, error.AsCString());
- }
-
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
if (log)
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsScript]), resname.c_str(), cachedir.c_str());
-
- if (resname.size() > 0)
- {
- StreamString strm;
- strm.Printf("librs.%s.so", resname.c_str());
-
- ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
- if (script)
- {
- script->type = ScriptDetails::eScriptC;
- script->cacheDir = cachedir;
- script->resName = resname;
- script->scriptDyLib = strm.GetData();
- script->context = addr_t(args[eRsContext]);
- }
-
- if (log)
- log->Printf("%s - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", __FUNCTION__,
- strm.GetData(), uint64_t(args[eRsContext]), uint64_t(args[eRsScript]));
- }
- else if (log)
- {
- log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__);
- }
-}
-
-void
-RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!module)
- {
- return;
- }
-
- Target &target = GetProcess()->GetTarget();
- llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
-
- if (targetArchType != llvm::Triple::ArchType::x86 &&
- targetArchType != llvm::Triple::ArchType::arm &&
- targetArchType != llvm::Triple::ArchType::aarch64 &&
- targetArchType != llvm::Triple::ArchType::mipsel &&
- targetArchType != llvm::Triple::ArchType::mips64el &&
- targetArchType != llvm::Triple::ArchType::x86_64)
- {
- if (log)
- log->Printf("%s - unable to hook runtime functions.", __FUNCTION__);
- return;
- }
-
- uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
-
- for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
- {
- const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
- if (hook_defn->kind != kind)
- {
- continue;
- }
-
- const char *symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
-
- const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
- if (!sym)
- {
- if (log)
- {
- log->Printf("%s - symbol '%s' related to the function %s not found",
- __FUNCTION__, symbol_name, hook_defn->name);
- }
- continue;
- }
-
- addr_t addr = sym->GetLoadAddress(&target);
- if (addr == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("%s - unable to resolve the address of hook function '%s' with symbol '%s'.",
- __FUNCTION__, hook_defn->name, symbol_name);
- continue;
- }
- else
- {
- if (log)
- log->Printf("%s - function %s, address resolved at 0x%" PRIx64,
- __FUNCTION__, hook_defn->name, addr);
- }
-
- RuntimeHookSP hook(new RuntimeHook());
- hook->address = addr;
- hook->defn = hook_defn;
- hook->bp_sp = target.CreateBreakpoint(addr, true, false);
- hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
- m_runtimeHooks[addr] = hook;
- if (log)
- {
- log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
- __FUNCTION__, hook_defn->name, module->GetFileSpec().GetFilename().AsCString(),
- (uint64_t)hook_defn->version, (uint64_t)addr);
- }
- }
-}
-
-void
-RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
-{
- if (!rsmodule_sp)
- return;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- const ModuleSP module = rsmodule_sp->m_module;
- const FileSpec &file = module->GetPlatformFileSpec();
-
- // Iterate over all of the scripts that we currently know of.
- // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
- for (const auto &rs_script : m_scripts)
- {
- // Extract the expected .so file path for this script.
- std::string dylib;
- if (!rs_script->scriptDyLib.get(dylib))
- continue;
-
- // Only proceed if the module that has loaded corresponds to this script.
- if (file.GetFilename() != ConstString(dylib.c_str()))
- continue;
-
- // Obtain the script address which we use as a key.
- lldb::addr_t script;
- if (!rs_script->script.get(script))
- continue;
-
- // If we have a script mapping for the current script.
- if (m_scriptMappings.find(script) != m_scriptMappings.end())
- {
- // if the module we have stored is different to the one we just received.
- if (m_scriptMappings[script] != rsmodule_sp)
- {
- if (log)
- log->Printf("%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", __FUNCTION__,
- (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
- // We don't have a script mapping for the current script.
- else
- {
- // Obtain the script resource name.
- std::string resName;
- if (rs_script->resName.get(resName))
- // Set the modules resource name.
- rsmodule_sp->m_resname = resName;
- // Add Script/Module pair to map.
- m_scriptMappings[script] = rsmodule_sp;
- if (log)
- log->Printf("%s - script %" PRIx64 " associated with rsmodule '%s'.", __FUNCTION__,
- (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
-}
-
-// Uses the Target API to evaluate the expression passed as a parameter to the function
-// The result of that expression is returned an unsigned 64 bit int, via the result* parameter.
-// Function returns true on success, and false on failure
-bool
-RenderScriptRuntime::EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (log)
- log->Printf("%s(%s)", __FUNCTION__, expression);
-
- ValueObjectSP expr_result;
- EvaluateExpressionOptions options;
- options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
- // Perform the actual expression evaluation
- GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result, options);
-
- if (!expr_result)
- {
- if (log)
- log->Printf("%s: couldn't evaluate expression.", __FUNCTION__);
- return false;
- }
-
- // The result of the expression is invalid
- if (!expr_result->GetError().Success())
- {
- Error err = expr_result->GetError();
- if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
- {
- if (log)
- log->Printf("%s - expression returned void.", __FUNCTION__);
-
- result = nullptr;
- return true;
- }
-
- if (log)
- log->Printf("%s - error evaluating expression result: %s", __FUNCTION__,
- err.AsCString());
- return false;
- }
-
- bool success = false;
- *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an uint32_t.
-
- if (!success)
- {
- if (log)
- log->Printf("%s - couldn't convert expression result to uint32_t", __FUNCTION__);
- return false;
- }
-
- return true;
-}
-
-namespace
-{
-// Used to index expression format strings
-enum ExpressionStrings
-{
- eExprGetOffsetPtr = 0,
- eExprAllocGetType,
- eExprTypeDimX,
- eExprTypeDimY,
- eExprTypeDimZ,
- eExprTypeElemPtr,
- eExprElementType,
- eExprElementKind,
- eExprElementVec,
- eExprElementFieldCount,
- eExprSubelementsId,
- eExprSubelementsName,
- eExprSubelementsArrSize,
-
- _eExprLast // keep at the end, implicit size of the array runtimeExpressions
-};
-
-// max length of an expanded expression
-const int jit_max_expr_size = 512;
-
-// Retrieve the string to JIT for the given expression
-const char*
-JITTemplate(ExpressionStrings e)
-{
- // Format strings containing the expressions we may need to evaluate.
- static std::array<const char*, _eExprLast> runtimeExpressions = {{
- // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
- "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace"
- "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)",
-
- // Type* rsaAllocationGetType(Context*, Allocation*)
- "(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")",
-
- // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
- // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
- // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
- // Need to specify 32 or 64 bit for uint_t since this differs between devices
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[0]", // X dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[1]", // Y dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[2]", // Z dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[5]", // Element ptr
-
- // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
- // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[0]", // Type
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[1]", // Kind
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[4]", // Field Count
-
- // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
- // size_t *arraySizes, uint32_t dataSize)
- // Needed for Allocations of structs to gather details about fields/Subelements
- // Element* of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]",
-
- // Name of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]",
-
- // Array size of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"
- }};
-
- return runtimeExpressions[e];
-}
-} // end of the anonymous namespace
-
-
-// JITs the RS runtime for the internal data pointer of an allocation.
-// Is passed x,y,z coordinates for the pointer to a specific element.
-// Then sets the data_ptr member in Allocation with the result.
-// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr, uint32_t x,
- uint32_t y, uint32_t z)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!allocation->address.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
-
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
-
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- allocation->data_ptr = mem_ptr;
-
- return true;
-}
-
-// JITs the RS runtime for the internal pointer to the RS Type of an allocation
-// Then sets the type_ptr member in Allocation with the result.
-// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!allocation->address.isValid() || !allocation->context.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- const char *expr_cstr = JITTemplate(eExprAllocGetType);
- char buffer[jit_max_expr_size];
-
- int chars_written =
- snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t type_ptr = static_cast<lldb::addr_t>(result);
- allocation->type_ptr = type_ptr;
+ addr_t type_ptr = static_cast<lldb::addr_t>(result);
+ allocation->type_ptr = type_ptr;
- return true;
+ return true;
}
-// JITs the RS runtime for information about the dimensions and type of an allocation
+// JITs the RS runtime for information about the dimensions and type of an
+// allocation
// Then sets dimension and element_ptr members in Allocation with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITTypePacked(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
- {
- if (log)
- log->Printf("%s - Failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- // Expression is different depending on if device is 32 or 64 bit
- uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
- const uint32_t bits = archByteSize == 4 ? 32 : 64;
-
- // We want 4 elements from packed data
- const uint32_t num_exprs = 4;
- assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
-
- char buffer[num_exprs][jit_max_expr_size];
- uint64_t results[num_exprs];
-
- for (uint32_t i = 0; i < num_exprs; ++i)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
- int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits, *allocation->context.get(),
- *allocation->type_ptr.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
- return false;
- }
+ if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) {
+ if (log)
+ log->Printf("%s - Failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- // Assign results to allocation members
- AllocationDetails::Dimension dims;
- dims.dim_1 = static_cast<uint32_t>(results[0]);
- dims.dim_2 = static_cast<uint32_t>(results[1]);
- dims.dim_3 = static_cast<uint32_t>(results[2]);
- allocation->dimension = dims;
+ // Expression is different depending on if device is 32 or 64 bit
+ uint32_t archByteSize =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ const uint32_t bits = archByteSize == 4 ? 32 : 64;
+
+ // We want 4 elements from packed data
+ const uint32_t num_exprs = 4;
+ assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) &&
+ "Invalid number of expressions");
- addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
- allocation->element.element_ptr = elem_ptr;
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
- if (log)
- log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") Element*: 0x%" PRIx64 ".", __FUNCTION__,
- dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+ for (uint32_t i = 0; i < num_exprs; ++i) {
+ const char *expr_cstr = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
+ int chars_written =
+ snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits,
+ *allocation->context.get(), *allocation->type_ptr.get());
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ AllocationDetails::Dimension dims;
+ dims.dim_1 = static_cast<uint32_t>(results[0]);
+ dims.dim_2 = static_cast<uint32_t>(results[1]);
+ dims.dim_3 = static_cast<uint32_t>(results[2]);
+ allocation->dimension = dims;
+
+ addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
+ allocation->element.element_ptr = elem_ptr;
+
+ if (log)
+ log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32
+ ") Element*: 0x%" PRIx64 ".",
+ __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
- return true;
+ return true;
}
// JITs the RS runtime for information about the Element of an allocation
-// Then sets type, type_vec_size, field_count and type_kind members in Element with the result.
+// Then sets type, type_vec_size, field_count and type_kind members in Element
+// with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!elem.element_ptr.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- // We want 4 elements from packed data
- const uint32_t num_exprs = 4;
- assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions");
-
- char buffer[num_exprs][jit_max_expr_size];
- uint64_t results[num_exprs];
-
- for (uint32_t i = 0; i < num_exprs; i++)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprElementType + i));
- int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
- return false;
- }
-
- // Assign results to allocation members
- elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
- elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
- elem.type_vec_size = static_cast<uint32_t>(results[2]);
- elem.field_count = static_cast<uint32_t>(results[3]);
+bool RenderScriptRuntime::JITElementPacked(Element &elem,
+ const lldb::addr_t context,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (!elem.element_ptr.isValid()) {
if (log)
- log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32 ", vector size %" PRIu32 ", field count %" PRIu32,
- __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get());
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields
- if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
- return false;
+ // We want 4 elements from packed data
+ const uint32_t num_exprs = 4;
+ assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) &&
+ "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (uint32_t i = 0; i < num_exprs; i++) {
+ const char *expr_cstr =
+ JITTemplate(ExpressionStrings(eExprElementType + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr,
+ context, *elem.element_ptr.get());
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
+ elem.type_kind =
+ static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
+ elem.type_vec_size = static_cast<uint32_t>(results[2]);
+ elem.field_count = static_cast<uint32_t>(results[3]);
+
+ if (log)
+ log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32
+ ", vector size %" PRIu32 ", field count %" PRIu32,
+ __FUNCTION__, *elem.type.get(), *elem.type_kind.get(),
+ *elem.type_vec_size.get(), *elem.field_count.get());
+
+ // If this Element has subelements then JIT rsaElementGetSubElements() for
+ // details about its fields
+ if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
+ return false;
- return true;
+ return true;
}
-// JITs the RS runtime for information about the subelements/fields of a struct allocation
-// This is necessary for infering the struct type so we can pretty print the allocation's contents.
+// JITs the RS runtime for information about the subelements/fields of a struct
+// allocation
+// This is necessary for infering the struct type so we can pretty print the
+// allocation's contents.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITSubelements(Element &elem,
+ const lldb::addr_t context,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!elem.element_ptr.isValid() || !elem.field_count.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- const short num_exprs = 3;
- assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions");
-
- char expr_buffer[jit_max_expr_size];
- uint64_t results;
-
- // Iterate over struct fields.
- const uint32_t field_count = *elem.field_count.get();
- for (uint32_t field_index = 0; field_index < field_count; ++field_index)
- {
- Element child;
- for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
- int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr,
- field_count, field_count, field_count,
- context, *elem.element_ptr.get(), field_count, field_index);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
- return false;
-
- if (log)
- log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);
-
- switch (expr_index)
- {
- case 0: // Element* of child
- child.element_ptr = static_cast<addr_t>(results);
- break;
- case 1: // Name of child
- {
- lldb::addr_t address = static_cast<addr_t>(results);
- Error err;
- std::string name;
- GetProcess()->ReadCStringFromMemory(address, name, err);
- if (!err.Fail())
- child.type_name = ConstString(name);
- else
- {
- if (log)
- log->Printf("%s - warning: Couldn't read field name.", __FUNCTION__);
- }
- break;
- }
- case 2: // Array size of child
- child.array_size = static_cast<uint32_t>(results);
- break;
- }
- }
-
- // We need to recursively JIT each Element field of the struct since
- // structs can be nested inside structs.
- if (!JITElementPacked(child, context, frame_ptr))
- return false;
- elem.children.push_back(child);
- }
+ if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- // Try to infer the name of the struct type so we can pretty print the allocation contents.
- FindStructTypeName(elem, frame_ptr);
+ const short num_exprs = 3;
+ assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) &&
+ "Invalid number of expressions");
+
+ char expr_buffer[jit_max_expr_size];
+ uint64_t results;
+
+ // Iterate over struct fields.
+ const uint32_t field_count = *elem.field_count.get();
+ for (uint32_t field_index = 0; field_index < field_count; ++field_index) {
+ Element child;
+ for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) {
+ const char *expr_cstr =
+ JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
+ int chars_written =
+ snprintf(expr_buffer, jit_max_expr_size, expr_cstr, field_count,
+ field_count, field_count, context, *elem.element_ptr.get(),
+ field_count, field_index);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
+ return false;
+
+ if (log)
+ log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);
+
+ switch (expr_index) {
+ case 0: // Element* of child
+ child.element_ptr = static_cast<addr_t>(results);
+ break;
+ case 1: // Name of child
+ {
+ lldb::addr_t address = static_cast<addr_t>(results);
+ Error err;
+ std::string name;
+ GetProcess()->ReadCStringFromMemory(address, name, err);
+ if (!err.Fail())
+ child.type_name = ConstString(name);
+ else {
+ if (log)
+ log->Printf("%s - warning: Couldn't read field name.",
+ __FUNCTION__);
+ }
+ break;
+ }
+ case 2: // Array size of child
+ child.array_size = static_cast<uint32_t>(results);
+ break;
+ }
+ }
+
+ // We need to recursively JIT each Element field of the struct since
+ // structs can be nested inside structs.
+ if (!JITElementPacked(child, context, frame_ptr))
+ return false;
+ elem.children.push_back(child);
+ }
+
+ // Try to infer the name of the struct type so we can pretty print the
+ // allocation contents.
+ FindStructTypeName(elem, frame_ptr);
- return true;
+ return true;
}
// JITs the RS runtime for the address of the last element in the allocation.
-// The `elem_size` parameter represents the size of a single element, including padding.
+// The `elem_size` parameter represents the size of a single element, including
+// padding.
// Which is needed as an offset from the last element pointer.
-// Using this offset minus the starting address we can calculate the size of the allocation.
+// Using this offset minus the starting address we can calculate the size of the
+// allocation.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!allocation->address.isValid() || !allocation->dimension.isValid() || !allocation->data_ptr.isValid() ||
- !allocation->element.datum_size.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- // Find dimensions
- uint32_t dim_x = allocation->dimension.get()->dim_1;
- uint32_t dim_y = allocation->dimension.get()->dim_2;
- uint32_t dim_z = allocation->dimension.get()->dim_3;
-
- // Our plan of jitting the last element address doesn't seem to work for struct Allocations
- // Instead try to infer the size ourselves without any inter element padding.
- if (allocation->element.children.size() > 0)
- {
- if (dim_x == 0) dim_x = 1;
- if (dim_y == 0) dim_y = 1;
- if (dim_z == 0) dim_z = 1;
+bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->dimension.isValid() ||
+ !allocation->data_ptr.isValid() ||
+ !allocation->element.datum_size.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
+ // Find dimensions
+ uint32_t dim_x = allocation->dimension.get()->dim_1;
+ uint32_t dim_y = allocation->dimension.get()->dim_2;
+ uint32_t dim_z = allocation->dimension.get()->dim_3;
+
+ // Our plan of jitting the last element address doesn't seem to work for
+ // struct Allocations
+ // Instead try to infer the size ourselves without any inter element padding.
+ if (allocation->element.children.size() > 0) {
+ if (dim_x == 0)
+ dim_x = 1;
+ if (dim_y == 0)
+ dim_y = 1;
+ if (dim_z == 0)
+ dim_z = 1;
- if (log)
- log->Printf("%s - inferred size of struct allocation %" PRIu32 ".", __FUNCTION__,
- *allocation->size.get());
- return true;
- }
+ allocation->size =
+ dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
+ if (log)
+ log->Printf("%s - inferred size of struct allocation %" PRIu32 ".",
+ __FUNCTION__, *allocation->size.get());
+ return true;
+ }
- // Calculate last element
- dim_x = dim_x == 0 ? 0 : dim_x - 1;
- dim_y = dim_y == 0 ? 0 : dim_y - 1;
- dim_z = dim_z == 0 ? 0 : dim_z - 1;
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), dim_x, dim_y, dim_z);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ // Calculate last element
+ dim_x = dim_x == 0 ? 0 : dim_x - 1;
+ dim_y = dim_y == 0 ? 0 : dim_y - 1;
+ dim_z = dim_z == 0 ? 0 : dim_z - 1;
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), dim_x, dim_y, dim_z);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- // Find pointer to last element and add on size of an element
- allocation->size =
- static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get();
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ // Find pointer to last element and add on size of an element
+ allocation->size =
+ static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) +
+ *allocation->element.datum_size.get();
- return true;
+ return true;
}
-// JITs the RS runtime for information about the stride between rows in the allocation.
+// JITs the RS runtime for information about the stride between rows in the
+// allocation.
// This is done to detect padding, since allocated memory is 16-byte aligned.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITAllocationStride(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
+ if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 0, 1, 0);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), 0, 1, 0);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->stride =
+ static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
- return true;
+ return true;
}
// JIT all the current runtime info regarding an allocation
-bool
-RenderScriptRuntime::RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- // GetOffsetPointer()
- if (!JITDataPointer(allocation, frame_ptr))
- return false;
+bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ // GetOffsetPointer()
+ if (!JITDataPointer(allocation, frame_ptr))
+ return false;
- // rsaAllocationGetType()
- if (!JITTypePointer(allocation, frame_ptr))
- return false;
+ // rsaAllocationGetType()
+ if (!JITTypePointer(allocation, frame_ptr))
+ return false;
- // rsaTypeGetNativeData()
- if (!JITTypePacked(allocation, frame_ptr))
- return false;
+ // rsaTypeGetNativeData()
+ if (!JITTypePacked(allocation, frame_ptr))
+ return false;
- // rsaElementGetNativeData()
- if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr))
- return false;
+ // rsaElementGetNativeData()
+ if (!JITElementPacked(allocation->element, *allocation->context.get(),
+ frame_ptr))
+ return false;
- // Sets the datum_size member in Element
- SetElementSize(allocation->element);
+ // Sets the datum_size member in Element
+ SetElementSize(allocation->element);
- // Use GetOffsetPointer() to infer size of the allocation
- if (!JITAllocationSize(allocation, frame_ptr))
- return false;
+ // Use GetOffsetPointer() to infer size of the allocation
+ if (!JITAllocationSize(allocation, frame_ptr))
+ return false;
- return true;
+ return true;
}
-// Function attempts to set the type_name member of the paramaterised Element object.
+// Function attempts to set the type_name member of the paramaterised Element
+// object.
// This string should be the name of the struct type the Element represents.
// We need this string for pretty printing the Element to users.
-void
-RenderScriptRuntime::FindStructTypeName(Element &elem, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!elem.type_name.IsEmpty()) // Name already set
- return;
- else
- elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed
-
- // Find all the global variables from the script rs modules
- VariableList variable_list;
- for (auto module_sp : m_rsmodules)
- module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list);
-
- // Iterate over all the global variables looking for one with a matching type to the Element.
- // We make the assumption a match exists since there needs to be a global variable to reflect the
- // struct type back into java host code.
- for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index)
- {
- const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
- if (!var_sp)
- continue;
-
- ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
- if (!valobj_sp)
- continue;
-
- // Find the number of variable fields.
- // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for.
- // Don't check for equality since RS can add extra struct members for padding.
- size_t num_children = valobj_sp->GetNumChildren();
- if (num_children > elem.children.size() || num_children == 0)
- continue;
+void RenderScriptRuntime::FindStructTypeName(Element &elem,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.type_name.IsEmpty()) // Name already set
+ return;
+ else
+ elem.type_name = Element::GetFallbackStructName(); // Default type name if
+ // we don't succeed
+
+ // Find all the global variables from the script rs modules
+ VariableList variable_list;
+ for (auto module_sp : m_rsmodules)
+ module_sp->m_module->FindGlobalVariables(RegularExpression("."), true,
+ UINT32_MAX, variable_list);
+
+ // Iterate over all the global variables looking for one with a matching type
+ // to the Element.
+ // We make the assumption a match exists since there needs to be a global
+ // variable to reflect the
+ // struct type back into java host code.
+ for (uint32_t var_index = 0; var_index < variable_list.GetSize();
+ ++var_index) {
+ const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
+ if (!var_sp)
+ continue;
+
+ ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
+ if (!valobj_sp)
+ continue;
+
+ // Find the number of variable fields.
+ // If it has no fields, or more fields than our Element, then it can't be
+ // the struct we're looking for.
+ // Don't check for equality since RS can add extra struct members for
+ // padding.
+ size_t num_children = valobj_sp->GetNumChildren();
+ if (num_children > elem.children.size() || num_children == 0)
+ continue;
+
+ // Iterate over children looking for members with matching field names.
+ // If all the field names match, this is likely the struct we want.
+ //
+ // TODO: This could be made more robust by also checking children data
+ // sizes, or array size
+ bool found = true;
+ for (size_t child_index = 0; child_index < num_children; ++child_index) {
+ ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
+ if (!child ||
+ (child->GetName() != elem.children[child_index].type_name)) {
+ found = false;
+ break;
+ }
+ }
+
+ // RS can add extra struct members for padding in the format
+ // '#rs_padding_[0-9]+'
+ if (found && num_children < elem.children.size()) {
+ const uint32_t size_diff = elem.children.size() - num_children;
+ if (log)
+ log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__,
+ size_diff);
+
+ for (uint32_t padding_index = 0; padding_index < size_diff;
+ ++padding_index) {
+ const ConstString &name =
+ elem.children[num_children + padding_index].type_name;
+ if (strcmp(name.AsCString(), "#rs_padding") < 0)
+ found = false;
+ }
+ }
+
+ // We've found a global var with matching type
+ if (found) {
+ // Dereference since our Element type isn't a pointer.
+ if (valobj_sp->IsPointerType()) {
+ Error err;
+ ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
+ if (!err.Fail())
+ valobj_sp = deref_valobj;
+ }
+
+ // Save name of variable in Element.
+ elem.type_name = valobj_sp->GetTypeName();
+ if (log)
+ log->Printf("%s - element name set to %s", __FUNCTION__,
+ elem.type_name.AsCString());
- // Iterate over children looking for members with matching field names.
- // If all the field names match, this is likely the struct we want.
- //
- // TODO: This could be made more robust by also checking children data sizes, or array size
- bool found = true;
- for (size_t child_index = 0; child_index < num_children; ++child_index)
- {
- ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
- if (!child || (child->GetName() != elem.children[child_index].type_name))
- {
- found = false;
- break;
- }
- }
-
- // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+'
- if (found && num_children < elem.children.size())
- {
- const uint32_t size_diff = elem.children.size() - num_children;
- if (log)
- log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__, size_diff);
-
- for (uint32_t padding_index = 0; padding_index < size_diff; ++padding_index)
- {
- const ConstString &name = elem.children[num_children + padding_index].type_name;
- if (strcmp(name.AsCString(), "#rs_padding") < 0)
- found = false;
- }
- }
-
- // We've found a global var with matching type
- if (found)
- {
- // Dereference since our Element type isn't a pointer.
- if (valobj_sp->IsPointerType())
- {
- Error err;
- ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
- if (!err.Fail())
- valobj_sp = deref_valobj;
- }
-
- // Save name of variable in Element.
- elem.type_name = valobj_sp->GetTypeName();
- if (log)
- log->Printf("%s - element name set to %s", __FUNCTION__, elem.type_name.AsCString());
-
- return;
- }
+ return;
}
+ }
}
-// Function sets the datum_size member of Element. Representing the size of a single instance including padding.
+// Function sets the datum_size member of Element. Representing the size of a
+// single instance including padding.
// Assumes the relevant allocation information has already been jitted.
-void
-RenderScriptRuntime::SetElementSize(Element &elem)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- const Element::DataType type = *elem.type.get();
- assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && "Invalid allocation type");
-
- const uint32_t vec_size = *elem.type_vec_size.get();
- uint32_t data_size = 0;
- uint32_t padding = 0;
-
- // Element is of a struct type, calculate size recursively.
- if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))
- {
- for (Element &child : elem.children)
- {
- SetElementSize(child);
- const uint32_t array_size = child.array_size.isValid() ? *child.array_size.get() : 1;
- data_size += *child.datum_size.get() * array_size;
- }
- }
- // These have been packed already
- else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
- type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
- type == Element::RS_TYPE_UNSIGNED_4_4_4_4)
- {
- data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
- }
- else if (type < Element::RS_TYPE_ELEMENT)
- {
- data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
- if (vec_size == 3)
- padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
- }
- else
- data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
-
- elem.padding = padding;
- elem.datum_size = data_size + padding;
- if (log)
- log->Printf("%s - element size set to %" PRIu32, __FUNCTION__, data_size + padding);
+void RenderScriptRuntime::SetElementSize(Element &elem) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ const Element::DataType type = *elem.type.get();
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
+ "Invalid allocation type");
+
+ const uint32_t vec_size = *elem.type_vec_size.get();
+ uint32_t data_size = 0;
+ uint32_t padding = 0;
+
+ // Element is of a struct type, calculate size recursively.
+ if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) {
+ for (Element &child : elem.children) {
+ SetElementSize(child);
+ const uint32_t array_size =
+ child.array_size.isValid() ? *child.array_size.get() : 1;
+ data_size += *child.datum_size.get() * array_size;
+ }
+ }
+ // These have been packed already
+ else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
+ type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
+ type == Element::RS_TYPE_UNSIGNED_4_4_4_4) {
+ data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ } else if (type < Element::RS_TYPE_ELEMENT) {
+ data_size =
+ vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
+ if (vec_size == 3)
+ padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ } else
+ data_size =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+
+ elem.padding = padding;
+ elem.datum_size = data_size + padding;
+ if (log)
+ log->Printf("%s - element size set to %" PRIu32, __FUNCTION__,
+ data_size + padding);
}
-// Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
+// Given an allocation, this function copies the allocation contents from device
+// into a buffer on the heap.
// Returning a shared pointer to the buffer containing the data.
std::shared_ptr<uint8_t>
-RenderScriptRuntime::GetAllocationData(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- // JIT all the allocation details
- if (allocation->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info", __FUNCTION__);
+RenderScriptRuntime::GetAllocationData(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!RefreshAllocation(allocation, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
- return nullptr;
- }
- }
+ // JIT all the allocation details
+ if (allocation->shouldRefresh()) {
+ if (log)
+ log->Printf("%s - allocation details not calculated yet, jitting info",
+ __FUNCTION__);
- assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() &&
- allocation->element.type_vec_size.isValid() && allocation->size.isValid() &&
- "Allocation information not available");
-
- // Allocate a buffer to copy data into
- const uint32_t size = *allocation->size.get();
- std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
- if (!buffer)
- {
- if (log)
- log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer", __FUNCTION__, size);
- return nullptr;
- }
+ if (!RefreshAllocation(allocation, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
+ return nullptr;
+ }
+ }
+
+ assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() &&
+ allocation->element.type_vec_size.isValid() &&
+ allocation->size.isValid() && "Allocation information not available");
+
+ // Allocate a buffer to copy data into
+ const uint32_t size = *allocation->size.get();
+ std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
+ if (!buffer) {
+ if (log)
+ log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer",
+ __FUNCTION__, size);
+ return nullptr;
+ }
- // Read the inferior memory
- Error error;
- lldb::addr_t data_ptr = *allocation->data_ptr.get();
- GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - '%s' Couldn't read %" PRIu32 " bytes of allocation data from 0x%" PRIx64,
- __FUNCTION__, error.AsCString(), size, data_ptr);
- return nullptr;
- }
+ // Read the inferior memory
+ Error error;
+ lldb::addr_t data_ptr = *allocation->data_ptr.get();
+ GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - '%s' Couldn't read %" PRIu32
+ " bytes of allocation data from 0x%" PRIx64,
+ __FUNCTION__, error.AsCString(), size, data_ptr);
+ return nullptr;
+ }
- return buffer;
+ return buffer;
}
// Function copies data from a binary file into an allocation.
-// There is a header at the start of the file, FileHeader, before the data content itself.
-// Information from this header is used to display warnings to the user about incompatibilities
-bool
-RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- // Find allocation with the given id
- AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
- if (!alloc)
- return false;
-
- if (log)
- log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *alloc->address.get());
-
- // JIT all the allocation details
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
-
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
- return false;
- }
- }
-
- assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() &&
- alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available");
-
- // Check we can read from file
- FileSpec file(filename, true);
- if (!file.Exists())
- {
- strm.Printf("Error: File %s does not exist", filename);
- strm.EOL();
- return false;
- }
-
- if (!file.Readable())
- {
- strm.Printf("Error: File %s does not have readable permissions", filename);
- strm.EOL();
- return false;
- }
-
- // Read file into data buffer
- DataBufferSP data_sp(file.ReadFileContents());
-
- // Cast start of buffer to FileHeader and use pointer to read metadata
- void *file_buffer = data_sp->GetBytes();
- if (file_buffer == nullptr ||
- data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader)))
- {
- strm.Printf("Error: File %s does not contain enough data for header", filename);
- strm.EOL();
- return false;
- }
- const AllocationDetails::FileHeader *file_header = static_cast<AllocationDetails::FileHeader *>(file_buffer);
-
- // Check file starts with ascii characters "RSAD"
- if (memcmp(file_header->ident, "RSAD", 4))
- {
- strm.Printf("Error: File doesn't contain identifier for an RS allocation dump. Are you sure this is the correct file?");
- strm.EOL();
- return false;
- }
+// There is a header at the start of the file, FileHeader, before the data
+// content itself.
+// Information from this header is used to display warnings to the user about
+// incompatibilities
+bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
- // Look at the type of the root element in the header
- AllocationDetails::ElementHeader root_element_header;
- memcpy(&root_element_header, static_cast<uint8_t *>(file_buffer) + sizeof(AllocationDetails::FileHeader),
- sizeof(AllocationDetails::ElementHeader));
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__,
+ *alloc->address.get());
+ // JIT all the allocation details
+ if (alloc->shouldRefresh()) {
if (log)
- log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32, __FUNCTION__,
- root_element_header.type, root_element_header.element_size);
-
- // Check if the target allocation and file both have the same number of bytes for an Element
- if (*alloc->element.datum_size.get() != root_element_header.element_size)
- {
- strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32 " bytes, allocation %" PRIu32 " bytes",
- root_element_header.element_size, *alloc->element.datum_size.get());
- strm.EOL();
- }
-
- // Check if the target allocation and file both have the same type
- const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
- const uint32_t file_type = root_element_header.type;
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
- if (file_type > Element::RS_TYPE_FONT)
- {
- strm.Printf("Warning: File has unknown allocation type");
- strm.EOL();
- }
- else if (alloc_type != file_type)
- {
- // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
- uint32_t printable_target_type_index = alloc_type;
- uint32_t printable_head_type_index = file_type;
- if (alloc_type >= Element::RS_TYPE_ELEMENT && alloc_type <= Element::RS_TYPE_FONT)
- printable_target_type_index = static_cast<Element::DataType>((alloc_type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- if (file_type >= Element::RS_TYPE_ELEMENT && file_type <= Element::RS_TYPE_FONT)
- printable_head_type_index = static_cast<Element::DataType>((file_type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- const char *file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
- const char *target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
-
- strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", file_type_cstr,
- target_type_cstr);
- strm.EOL();
- }
-
- // Advance buffer past header
- file_buffer = static_cast<uint8_t *>(file_buffer) + file_header->hdr_size;
-
- // Calculate size of allocation data in file
- size_t length = data_sp->GetByteSize() - file_header->hdr_size;
-
- // Check if the target allocation and file both have the same total data size.
- const uint32_t alloc_size = *alloc->size.get();
- if (alloc_size != length)
- {
- strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%" PRIx32 " bytes",
- (uint64_t)length, alloc_size);
- strm.EOL();
- length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
- }
-
- // Copy file data from our buffer into the target allocation.
- lldb::addr_t alloc_data = *alloc->data_ptr.get();
- Error error;
- size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
- if (!error.Success() || bytes_written != length)
- {
- strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
- strm.EOL();
- return false;
- }
-
- strm.Printf("Contents of file '%s' read into allocation %" PRIu32, filename, alloc->id);
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
+ alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
+ alloc->element.datum_size.isValid() &&
+ "Allocation information not available");
+
+ // Check we can read from file
+ FileSpec file(filename, true);
+ if (!file.Exists()) {
+ strm.Printf("Error: File %s does not exist", filename);
strm.EOL();
+ return false;
+ }
- return true;
-}
-
-// Function takes as parameters a byte buffer, which will eventually be written to file as the element header,
-// an offset into that buffer, and an Element that will be saved into the buffer at the parametrised offset.
-// Return value is the new offset after writing the element into the buffer.
-// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's
-// children.
-size_t
-RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset,
- const Element &elem)
-{
- // File struct for an element header with all the relevant details copied from elem.
- // We assume members are valid already.
- AllocationDetails::ElementHeader elem_header;
- elem_header.type = *elem.type.get();
- elem_header.kind = *elem.type_kind.get();
- elem_header.element_size = *elem.datum_size.get();
- elem_header.vector_size = *elem.type_vec_size.get();
- elem_header.array_size = elem.array_size.isValid() ? *elem.array_size.get() : 0;
- const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
-
- // Copy struct into buffer and advance offset
- // We assume that header_buffer has been checked for nullptr before this method is called
- memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
- offset += elem_header_size;
-
- // Starting offset of child ElementHeader struct
- size_t child_offset = offset + ((elem.children.size() + 1) * sizeof(uint32_t));
- for (const RenderScriptRuntime::Element &child : elem.children)
- {
- // Recursively populate the buffer with the element header structs of children.
- // Then save the offsets where they were set after the parent element header.
- memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
- offset += sizeof(uint32_t);
+ if (!file.Readable()) {
+ strm.Printf("Error: File %s does not have readable permissions", filename);
+ strm.EOL();
+ return false;
+ }
- child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
- }
+ // Read file into data buffer
+ DataBufferSP data_sp(file.ReadFileContents());
- // Zero indicates no more children
- memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
+ // Cast start of buffer to FileHeader and use pointer to read metadata
+ void *file_buffer = data_sp->GetBytes();
+ if (file_buffer == nullptr ||
+ data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
+ sizeof(AllocationDetails::ElementHeader))) {
+ strm.Printf("Error: File %s does not contain enough data for header",
+ filename);
+ strm.EOL();
+ return false;
+ }
+ const AllocationDetails::FileHeader *file_header =
+ static_cast<AllocationDetails::FileHeader *>(file_buffer);
+
+ // Check file starts with ascii characters "RSAD"
+ if (memcmp(file_header->ident, "RSAD", 4)) {
+ strm.Printf("Error: File doesn't contain identifier for an RS allocation "
+ "dump. Are you sure this is the correct file?");
+ strm.EOL();
+ return false;
+ }
- return child_offset;
-}
+ // Look at the type of the root element in the header
+ AllocationDetails::ElementHeader root_element_header;
+ memcpy(&root_element_header, static_cast<uint8_t *>(file_buffer) +
+ sizeof(AllocationDetails::FileHeader),
+ sizeof(AllocationDetails::ElementHeader));
+
+ if (log)
+ log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32,
+ __FUNCTION__, root_element_header.type,
+ root_element_header.element_size);
+
+ // Check if the target allocation and file both have the same number of bytes
+ // for an Element
+ if (*alloc->element.datum_size.get() != root_element_header.element_size) {
+ strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32
+ " bytes, allocation %" PRIu32 " bytes",
+ root_element_header.element_size,
+ *alloc->element.datum_size.get());
+ strm.EOL();
+ }
-// Given an Element object this function returns the total size needed in the file header to store the element's
-// details.
-// Taking into account the size of the element header struct, plus the offsets to all the element's children.
-// Function is recursive so that the size of all ancestors is taken into account.
-size_t
-RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem)
-{
- size_t size = (elem.children.size() + 1) * sizeof(uint32_t); // Offsets to children plus zero terminator
- size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details
-
- // Calculate recursively for all descendants
- for (const Element &child : elem.children)
- size += CalculateElementHeaderSize(child);
+ // Check if the target allocation and file both have the same type
+ const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
+ const uint32_t file_type = root_element_header.type;
- return size;
-}
+ if (file_type > Element::RS_TYPE_FONT) {
+ strm.Printf("Warning: File has unknown allocation type");
+ strm.EOL();
+ } else if (alloc_type != file_type) {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString
+ // array
+ uint32_t printable_target_type_index = alloc_type;
+ uint32_t printable_head_type_index = file_type;
+ if (alloc_type >= Element::RS_TYPE_ELEMENT &&
+ alloc_type <= Element::RS_TYPE_FONT)
+ printable_target_type_index = static_cast<Element::DataType>(
+ (alloc_type - Element::RS_TYPE_ELEMENT) +
+ Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (file_type >= Element::RS_TYPE_ELEMENT &&
+ file_type <= Element::RS_TYPE_FONT)
+ printable_head_type_index = static_cast<Element::DataType>(
+ (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 +
+ 1);
+
+ const char *file_type_cstr =
+ AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
+ const char *target_type_cstr =
+ AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
+
+ strm.Printf(
+ "Warning: Mismatched Types - file '%s' type, allocation '%s' type",
+ file_type_cstr, target_type_cstr);
+ strm.EOL();
+ }
-// Function copies allocation contents into a binary file.
-// This file can then be loaded later into a different allocation.
-// There is a header, FileHeader, before the allocation data containing meta-data.
-bool
-RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ // Advance buffer past header
+ file_buffer = static_cast<uint8_t *>(file_buffer) + file_header->hdr_size;
- // Find allocation with the given id
- AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
- if (!alloc)
- return false;
+ // Calculate size of allocation data in file
+ size_t length = data_sp->GetByteSize() - file_header->hdr_size;
- if (log)
- log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, *alloc->address.get());
+ // Check if the target allocation and file both have the same total data size.
+ const uint32_t alloc_size = *alloc->size.get();
+ if (alloc_size != length) {
+ strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
+ " bytes, allocation 0x%" PRIx32 " bytes",
+ (uint64_t)length, alloc_size);
+ strm.EOL();
+ length = alloc_size < length ? alloc_size
+ : length; // Set length to copy to minimum
+ }
+
+ // Copy file data from our buffer into the target allocation.
+ lldb::addr_t alloc_data = *alloc->data_ptr.get();
+ Error error;
+ size_t bytes_written =
+ GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
+ if (!error.Success() || bytes_written != length) {
+ strm.Printf("Error: Couldn't write data to allocation %s",
+ error.AsCString());
+ strm.EOL();
+ return false;
+ }
- // JIT all the allocation details
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
+ strm.Printf("Contents of file '%s' read into allocation %" PRIu32, filename,
+ alloc->id);
+ strm.EOL();
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__);
- return false;
- }
- }
+ return true;
+}
- assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() &&
- alloc->element.datum_size.get() && alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
- "Allocation information not available");
-
- // Check we can create writable file
- FileSpec file_spec(filename, true);
- File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
- if (!file)
- {
- strm.Printf("Error: Failed to open '%s' for writing", filename);
- strm.EOL();
- return false;
- }
+// Function takes as parameters a byte buffer, which will eventually be written
+// to file as the element header,
+// an offset into that buffer, and an Element that will be saved into the buffer
+// at the parametrised offset.
+// Return value is the new offset after writing the element into the buffer.
+// Elements are saved to the file as the ElementHeader struct followed by
+// offsets to the structs of all the element's
+// children.
+size_t RenderScriptRuntime::PopulateElementHeaders(
+ const std::shared_ptr<uint8_t> header_buffer, size_t offset,
+ const Element &elem) {
+ // File struct for an element header with all the relevant details copied from
+ // elem.
+ // We assume members are valid already.
+ AllocationDetails::ElementHeader elem_header;
+ elem_header.type = *elem.type.get();
+ elem_header.kind = *elem.type_kind.get();
+ elem_header.element_size = *elem.datum_size.get();
+ elem_header.vector_size = *elem.type_vec_size.get();
+ elem_header.array_size =
+ elem.array_size.isValid() ? *elem.array_size.get() : 0;
+ const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
+
+ // Copy struct into buffer and advance offset
+ // We assume that header_buffer has been checked for nullptr before this
+ // method is called
+ memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
+ offset += elem_header_size;
+
+ // Starting offset of child ElementHeader struct
+ size_t child_offset =
+ offset + ((elem.children.size() + 1) * sizeof(uint32_t));
+ for (const RenderScriptRuntime::Element &child : elem.children) {
+ // Recursively populate the buffer with the element header structs of
+ // children.
+ // Then save the offsets where they were set after the parent element
+ // header.
+ memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
+ }
- // Read allocation into buffer of heap memory
- const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
- if (!buffer)
- {
- strm.Printf("Error: Couldn't read allocation data into buffer");
- strm.EOL();
- return false;
- }
+ // Zero indicates no more children
+ memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
- // Create the file header
- AllocationDetails::FileHeader head;
- memcpy(head.ident, "RSAD", 4);
- head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
- head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
- head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
-
- const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
- assert((sizeof(AllocationDetails::FileHeader) + element_header_size) < UINT16_MAX && "Element header too large");
- head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) + element_header_size);
+ return child_offset;
+}
- // Write the file header
- size_t num_bytes = sizeof(AllocationDetails::FileHeader);
- if (log)
- log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes);
+// Given an Element object this function returns the total size needed in the
+// file header to store the element's
+// details.
+// Taking into account the size of the element header struct, plus the offsets
+// to all the element's children.
+// Function is recursive so that the size of all ancestors is taken into
+// account.
+size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
+ size_t size = (elem.children.size() + 1) *
+ sizeof(uint32_t); // Offsets to children plus zero terminator
+ size += sizeof(AllocationDetails::ElementHeader); // Size of header struct
+ // with type details
+
+ // Calculate recursively for all descendants
+ for (const Element &child : elem.children)
+ size += CalculateElementHeaderSize(child);
- Error err = file.Write(&head, num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
+ return size;
+}
- // Create the headers describing the element type of the allocation.
- std::shared_ptr<uint8_t> element_header_buffer(new uint8_t[element_header_size]);
- if (element_header_buffer == nullptr)
- {
- strm.Printf("Internal Error: Couldn't allocate %" PRIu64 " bytes on the heap", (uint64_t)element_header_size);
- strm.EOL();
- return false;
- }
+// Function copies allocation contents into a binary file.
+// This file can then be loaded later into a different allocation.
+// There is a header, FileHeader, before the allocation data containing
+// meta-data.
+bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
- PopulateElementHeaders(element_header_buffer, 0, alloc->element);
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__,
+ *alloc->address.get());
- // Write headers for allocation element type to file
- num_bytes = element_header_size;
+ // JIT all the allocation details
+ if (alloc->shouldRefresh()) {
if (log)
- log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.", __FUNCTION__, (uint64_t)num_bytes);
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
- err = file.Write(element_header_buffer.get(), num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__);
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
+ alloc->element.type_vec_size.isValid() &&
+ alloc->element.datum_size.get() &&
+ alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
+ "Allocation information not available");
+
+ // Check we can create writable file
+ FileSpec file_spec(filename, true);
+ File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
+ File::eOpenOptionTruncate);
+ if (!file) {
+ strm.Printf("Error: Failed to open '%s' for writing", filename);
+ strm.EOL();
+ return false;
+ }
- // Write allocation data to file
- num_bytes = static_cast<size_t>(*alloc->size.get());
- if (log)
- log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes);
+ // Read allocation into buffer of heap memory
+ const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer) {
+ strm.Printf("Error: Couldn't read allocation data into buffer");
+ strm.EOL();
+ return false;
+ }
- err = file.Write(buffer.get(), num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
+ // Create the file header
+ AllocationDetails::FileHeader head;
+ memcpy(head.ident, "RSAD", 4);
+ head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
+ head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
+ head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
+
+ const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
+ assert((sizeof(AllocationDetails::FileHeader) + element_header_size) <
+ UINT16_MAX &&
+ "Element header too large");
+ head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) +
+ element_header_size);
+
+ // Write the file header
+ size_t num_bytes = sizeof(AllocationDetails::FileHeader);
+ if (log)
+ log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
+ (uint64_t)num_bytes);
+
+ Error err = file.Write(&head, num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
+ return false;
+ }
- strm.Printf("Allocation written to file '%s'", filename);
+ // Create the headers describing the element type of the allocation.
+ std::shared_ptr<uint8_t> element_header_buffer(
+ new uint8_t[element_header_size]);
+ if (element_header_buffer == nullptr) {
+ strm.Printf("Internal Error: Couldn't allocate %" PRIu64
+ " bytes on the heap",
+ (uint64_t)element_header_size);
strm.EOL();
- return true;
-}
+ return false;
+ }
-bool
-RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ PopulateElementHeaders(element_header_buffer, 0, alloc->element);
- if (module_sp)
- {
- for (const auto &rs_module : m_rsmodules)
- {
- if (rs_module->m_module == module_sp)
- {
- // Check if the user has enabled automatically breaking on
- // all RS kernels.
- if (m_breakAllKernels)
- BreakOnModuleKernels(rs_module);
+ // Write headers for allocation element type to file
+ num_bytes = element_header_size;
+ if (log)
+ log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.",
+ __FUNCTION__, (uint64_t)num_bytes);
+
+ err = file.Write(element_header_buffer.get(), num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
+ return false;
+ }
- return false;
- }
- }
- bool module_loaded = false;
- switch (GetModuleKind(module_sp))
- {
- case eModuleKindKernelObj:
- {
- RSModuleDescriptorSP module_desc;
- module_desc.reset(new RSModuleDescriptor(module_sp));
- if (module_desc->ParseRSInfo())
- {
- m_rsmodules.push_back(module_desc);
- module_loaded = true;
- }
- if (module_loaded)
- {
- FixupScriptDetails(module_desc);
- }
- break;
- }
- case eModuleKindDriver:
- {
- if (!m_libRSDriver)
- {
- m_libRSDriver = module_sp;
- LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
- }
- break;
- }
- case eModuleKindImpl:
- {
- m_libRSCpuRef = module_sp;
- break;
- }
- case eModuleKindLibRS:
- {
- if (!m_libRS)
- {
- m_libRS = module_sp;
- static ConstString gDbgPresentStr("gDebuggerPresent");
- const Symbol *debug_present =
- m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
- if (debug_present)
- {
- Error error;
- uint32_t flag = 0x00000001U;
- Target &target = GetProcess()->GetTarget();
- addr_t addr = debug_present->GetLoadAddress(&target);
- GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
- if (error.Success())
- {
- if (log)
- log->Printf("%s - debugger present flag set on debugee.", __FUNCTION__);
-
- m_debuggerPresentFlagged = true;
- }
- else if (log)
- {
- log->Printf("%s - error writing debugger present flags '%s' ", __FUNCTION__,
- error.AsCString());
- }
- }
- else if (log)
- {
- log->Printf("%s - error writing debugger present flags - symbol not found", __FUNCTION__);
- }
- }
- break;
- }
- default:
- break;
- }
- if (module_loaded)
- Update();
- return module_loaded;
- }
+ // Write allocation data to file
+ num_bytes = static_cast<size_t>(*alloc->size.get());
+ if (log)
+ log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
+ (uint64_t)num_bytes);
+
+ err = file.Write(buffer.get(), num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
return false;
-}
+ }
-void
-RenderScriptRuntime::Update()
-{
- if (m_rsmodules.size() > 0)
- {
- if (!m_initiated)
- {
- Initiate();
- }
+ strm.Printf("Allocation written to file '%s'", filename);
+ strm.EOL();
+ return true;
+}
+
+bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (module_sp) {
+ for (const auto &rs_module : m_rsmodules) {
+ if (rs_module->m_module == module_sp) {
+ // Check if the user has enabled automatically breaking on
+ // all RS kernels.
+ if (m_breakAllKernels)
+ BreakOnModuleKernels(rs_module);
+
+ return false;
+ }
+ }
+ bool module_loaded = false;
+ switch (GetModuleKind(module_sp)) {
+ case eModuleKindKernelObj: {
+ RSModuleDescriptorSP module_desc;
+ module_desc.reset(new RSModuleDescriptor(module_sp));
+ if (module_desc->ParseRSInfo()) {
+ m_rsmodules.push_back(module_desc);
+ module_loaded = true;
+ }
+ if (module_loaded) {
+ FixupScriptDetails(module_desc);
+ }
+ break;
+ }
+ case eModuleKindDriver: {
+ if (!m_libRSDriver) {
+ m_libRSDriver = module_sp;
+ LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
+ }
+ break;
+ }
+ case eModuleKindImpl: {
+ m_libRSCpuRef = module_sp;
+ break;
+ }
+ case eModuleKindLibRS: {
+ if (!m_libRS) {
+ m_libRS = module_sp;
+ static ConstString gDbgPresentStr("gDebuggerPresent");
+ const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType(
+ gDbgPresentStr, eSymbolTypeData);
+ if (debug_present) {
+ Error error;
+ uint32_t flag = 0x00000001U;
+ Target &target = GetProcess()->GetTarget();
+ addr_t addr = debug_present->GetLoadAddress(&target);
+ GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
+ if (error.Success()) {
+ if (log)
+ log->Printf("%s - debugger present flag set on debugee.",
+ __FUNCTION__);
+
+ m_debuggerPresentFlagged = true;
+ } else if (log) {
+ log->Printf("%s - error writing debugger present flags '%s' ",
+ __FUNCTION__, error.AsCString());
+ }
+ } else if (log) {
+ log->Printf(
+ "%s - error writing debugger present flags - symbol not found",
+ __FUNCTION__);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (module_loaded)
+ Update();
+ return module_loaded;
+ }
+ return false;
+}
+
+void RenderScriptRuntime::Update() {
+ if (m_rsmodules.size() > 0) {
+ if (!m_initiated) {
+ Initiate();
}
+ }
}
// The maximum line length of an .rs.info packet
@@ -2673,501 +2593,477 @@ RenderScriptRuntime::Update()
#define MAXLINESTR_(x) "%" STRINGIFY(x) "s"
#define MAXLINESTR MAXLINESTR_(MAXLINE)
-// The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
+// The .rs.info symbol in renderscript modules contains a string which needs to
+// be parsed.
// The string is basic and is parsed on a line by line basis.
-bool
-RSModuleDescriptor::ParseRSInfo()
-{
- assert(m_module);
- const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
- if (!info_sym)
- return false;
-
- const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
- if (addr == LLDB_INVALID_ADDRESS)
- return false;
-
- const addr_t size = info_sym->GetByteSize();
- const FileSpec fs = m_module->GetFileSpec();
-
- const DataBufferSP buffer = fs.ReadFileContents(addr, size);
- if (!buffer)
- return false;
-
- // split rs.info. contents into lines
- std::vector<std::string> info_lines;
- {
- const std::string info((const char *)buffer->GetBytes());
- for (size_t tail = 0; tail < info.size();)
- {
- // find next new line or end of string
- size_t head = info.find('\n', tail);
- head = (head == std::string::npos) ? info.size() : head;
- std::string line = info.substr(tail, head - tail);
- // add to line list
- info_lines.push_back(line);
- tail = head + 1;
- }
- }
+bool RSModuleDescriptor::ParseRSInfo() {
+ assert(m_module);
+ const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(
+ ConstString(".rs.info"), eSymbolTypeData);
+ if (!info_sym)
+ return false;
- std::array<char, MAXLINE> name{{'\0'}};
- std::array<char, MAXLINE> value{{'\0'}};
+ const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
- // parse all text lines of .rs.info
- for (auto line = info_lines.begin(); line != info_lines.end(); ++line)
- {
- uint32_t numDefns = 0;
- if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str()));
- }
- else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- {
- uint32_t slot = 0;
- name[0] = '\0';
- static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR;
- if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2)
- {
- if (name[0] != '\0')
- m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot));
- }
- }
- }
- else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- {
- name[0] = value[0] = '\0';
- static const char *fmt_s = MAXLINESTR " - " MAXLINESTR;
- if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0)
- {
- if (name[0] != '\0')
- m_pragmas[std::string(name.data())] = value.data();
- }
- }
- }
- else
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (log)
- {
- log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, line->c_str());
- }
- }
- }
+ const addr_t size = info_sym->GetByteSize();
+ const FileSpec fs = m_module->GetFileSpec();
- // 'root' kernel should always be present
- return m_kernels.size() > 0;
-}
+ const DataBufferSP buffer = fs.ReadFileContents(addr, size);
+ if (!buffer)
+ return false;
-void
-RenderScriptRuntime::Status(Stream &strm) const
-{
- if (m_libRS)
- {
- strm.Printf("Runtime Library discovered.");
- strm.EOL();
- }
- if (m_libRSDriver)
- {
- strm.Printf("Runtime Driver discovered.");
- strm.EOL();
- }
- if (m_libRSCpuRef)
- {
- strm.Printf("CPU Reference Implementation discovered.");
- strm.EOL();
- }
+ // split rs.info. contents into lines
+ std::vector<std::string> info_lines;
+ {
+ const std::string info((const char *)buffer->GetBytes());
+ for (size_t tail = 0; tail < info.size();) {
+ // find next new line or end of string
+ size_t head = info.find('\n', tail);
+ head = (head == std::string::npos) ? info.size() : head;
+ std::string line = info.substr(tail, head - tail);
+ // add to line list
+ info_lines.push_back(line);
+ tail = head + 1;
+ }
+ }
+
+ std::array<char, MAXLINE> name{{'\0'}};
+ std::array<char, MAXLINE> value{{'\0'}};
+
+ // parse all text lines of .rs.info
+ for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {
+ uint32_t numDefns = 0;
+ if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1) {
+ while (numDefns--)
+ m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str()));
+ } else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "",
+ &numDefns) == 1) {
+ while (numDefns--) {
+ uint32_t slot = 0;
+ name[0] = '\0';
+ static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR;
+ if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2) {
+ if (name[0] != '\0')
+ m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot));
+ }
+ }
+ } else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) ==
+ 1) {
+ while (numDefns--) {
+ name[0] = value[0] = '\0';
+ static const char *fmt_s = MAXLINESTR " - " MAXLINESTR;
+ if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0) {
+ if (name[0] != '\0')
+ m_pragmas[std::string(name.data())] = value.data();
+ }
+ }
+ } else {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log) {
+ log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__,
+ line->c_str());
+ }
+ }
+ }
+
+ // 'root' kernel should always be present
+ return m_kernels.size() > 0;
+}
+
+void RenderScriptRuntime::Status(Stream &strm) const {
+ if (m_libRS) {
+ strm.Printf("Runtime Library discovered.");
+ strm.EOL();
+ }
+ if (m_libRSDriver) {
+ strm.Printf("Runtime Driver discovered.");
+ strm.EOL();
+ }
+ if (m_libRSCpuRef) {
+ strm.Printf("CPU Reference Implementation discovered.");
+ strm.EOL();
+ }
- if (m_runtimeHooks.size())
- {
- strm.Printf("Runtime functions hooked:");
- strm.EOL();
- for (auto b : m_runtimeHooks)
- {
- strm.Indent(b.second->defn->name);
- strm.EOL();
- }
- }
- else
- {
- strm.Printf("Runtime is not hooked.");
- strm.EOL();
+ if (m_runtimeHooks.size()) {
+ strm.Printf("Runtime functions hooked:");
+ strm.EOL();
+ for (auto b : m_runtimeHooks) {
+ strm.Indent(b.second->defn->name);
+ strm.EOL();
}
+ } else {
+ strm.Printf("Runtime is not hooked.");
+ strm.EOL();
+ }
}
-void
-RenderScriptRuntime::DumpContexts(Stream &strm) const
-{
- strm.Printf("Inferred RenderScript Contexts:");
+void RenderScriptRuntime::DumpContexts(Stream &strm) const {
+ strm.Printf("Inferred RenderScript Contexts:");
+ strm.EOL();
+ strm.IndentMore();
+
+ std::map<addr_t, uint64_t> contextReferences;
+
+ // Iterate over all of the currently discovered scripts.
+ // Note: We cant push or pop from m_scripts inside this loop or it may
+ // invalidate script.
+ for (const auto &script : m_scripts) {
+ if (!script->context.isValid())
+ continue;
+ lldb::addr_t context = *script->context;
+
+ if (contextReferences.find(context) != contextReferences.end()) {
+ contextReferences[context]++;
+ } else {
+ contextReferences[context] = 1;
+ }
+ }
+
+ for (const auto &cRef : contextReferences) {
+ strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances",
+ cRef.first, cRef.second);
strm.EOL();
- strm.IndentMore();
-
- std::map<addr_t, uint64_t> contextReferences;
-
- // Iterate over all of the currently discovered scripts.
- // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
- for (const auto &script : m_scripts)
- {
- if (!script->context.isValid())
- continue;
- lldb::addr_t context = *script->context;
-
- if (contextReferences.find(context) != contextReferences.end())
- {
- contextReferences[context]++;
- }
- else
- {
- contextReferences[context] = 1;
- }
- }
-
- for (const auto &cRef : contextReferences)
- {
- strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
- strm.EOL();
- }
- strm.IndentLess();
+ }
+ strm.IndentLess();
}
-void
-RenderScriptRuntime::DumpKernels(Stream &strm) const
-{
- strm.Printf("RenderScript Kernels:");
+void RenderScriptRuntime::DumpKernels(Stream &strm) const {
+ strm.Printf("RenderScript Kernels:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules) {
+ strm.Printf("Resource '%s':", module->m_resname.c_str());
strm.EOL();
- strm.IndentMore();
- for (const auto &module : m_rsmodules)
- {
- strm.Printf("Resource '%s':", module->m_resname.c_str());
- strm.EOL();
- for (const auto &kernel : module->m_kernels)
- {
- strm.Indent(kernel.m_name.AsCString());
- strm.EOL();
- }
+ for (const auto &kernel : module->m_kernels) {
+ strm.Indent(kernel.m_name.AsCString());
+ strm.EOL();
}
- strm.IndentLess();
+ }
+ strm.IndentLess();
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
-{
- AllocationDetails *alloc = nullptr;
-
- // See if we can find allocation using id as an index;
- if (alloc_id <= m_allocations.size() && alloc_id != 0 && m_allocations[alloc_id - 1]->id == alloc_id)
- {
- alloc = m_allocations[alloc_id - 1].get();
- return alloc;
- }
-
- // Fallback to searching
- for (const auto &a : m_allocations)
- {
- if (a->id == alloc_id)
- {
- alloc = a.get();
- break;
- }
- }
-
- if (alloc == nullptr)
- {
- strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32, alloc_id);
- strm.EOL();
- }
+RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) {
+ AllocationDetails *alloc = nullptr;
+ // See if we can find allocation using id as an index;
+ if (alloc_id <= m_allocations.size() && alloc_id != 0 &&
+ m_allocations[alloc_id - 1]->id == alloc_id) {
+ alloc = m_allocations[alloc_id - 1].get();
return alloc;
-}
-
-// Prints the contents of an allocation to the output stream, which may be a file
-bool
-RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- // Check we can find the desired allocation
- AllocationDetails *alloc = FindAllocByID(strm, id);
- if (!alloc)
- return false; // FindAllocByID() will print error message for us here
-
- if (log)
- log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *alloc->address.get());
-
- // Check we have information about the allocation, if not calculate it
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
+ }
- // JIT all the allocation information
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- strm.Printf("Error: Couldn't JIT allocation details");
- strm.EOL();
- return false;
- }
- }
+ // Fallback to searching
+ for (const auto &a : m_allocations) {
+ if (a->id == alloc_id) {
+ alloc = a.get();
+ break;
+ }
+ }
+
+ if (alloc == nullptr) {
+ strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32,
+ alloc_id);
+ strm.EOL();
+ }
- // Establish format and size of each data element
- const uint32_t vec_size = *alloc->element.type_vec_size.get();
- const Element::DataType type = *alloc->element.type.get();
-
- assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && "Invalid allocation type");
-
- lldb::Format format;
- if (type >= Element::RS_TYPE_ELEMENT)
- format = eFormatHex;
- else
- format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
- : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
+ return alloc;
+}
- const uint32_t data_size = *alloc->element.datum_size.get();
+// Prints the contents of an allocation to the output stream, which may be a
+// file
+bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t id) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (log)
- log->Printf("%s - element size %" PRIu32 " bytes, including padding", __FUNCTION__, data_size);
+ // Check we can find the desired allocation
+ AllocationDetails *alloc = FindAllocByID(strm, id);
+ if (!alloc)
+ return false; // FindAllocByID() will print error message for us here
- // Allocate a buffer to copy data into
- std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
- if (!buffer)
- {
- strm.Printf("Error: Couldn't read allocation data");
- strm.EOL();
- return false;
- }
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__,
+ *alloc->address.get());
- // Calculate stride between rows as there may be padding at end of rows since
- // allocated memory is 16-byte aligned
- if (!alloc->stride.isValid())
- {
- if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
- alloc->stride = 0;
- else if (!JITAllocationStride(alloc, frame_ptr))
- {
- strm.Printf("Error: Couldn't calculate allocation row stride");
- strm.EOL();
- return false;
- }
- }
- const uint32_t stride = *alloc->stride.get();
- const uint32_t size = *alloc->size.get(); // Size of whole allocation
- const uint32_t padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
+ // Check we have information about the allocation, if not calculate it
+ if (alloc->shouldRefresh()) {
if (log)
- log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32 " bytes, padding %" PRIu32,
- __FUNCTION__, stride, size, padding);
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
- // Find dimensions used to index loops, so need to be non-zero
- uint32_t dim_x = alloc->dimension.get()->dim_1;
- dim_x = dim_x == 0 ? 1 : dim_x;
-
- uint32_t dim_y = alloc->dimension.get()->dim_2;
- dim_y = dim_y == 0 ? 1 : dim_y;
+ // JIT all the allocation information
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ strm.Printf("Error: Couldn't JIT allocation details");
+ strm.EOL();
+ return false;
+ }
+ }
+
+ // Establish format and size of each data element
+ const uint32_t vec_size = *alloc->element.type_vec_size.get();
+ const Element::DataType type = *alloc->element.type.get();
+
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
+ "Invalid allocation type");
+
+ lldb::Format format;
+ if (type >= Element::RS_TYPE_ELEMENT)
+ format = eFormatHex;
+ else
+ format = vec_size == 1
+ ? static_cast<lldb::Format>(
+ AllocationDetails::RSTypeToFormat[type][eFormatSingle])
+ : static_cast<lldb::Format>(
+ AllocationDetails::RSTypeToFormat[type][eFormatVector]);
+
+ const uint32_t data_size = *alloc->element.datum_size.get();
+
+ if (log)
+ log->Printf("%s - element size %" PRIu32 " bytes, including padding",
+ __FUNCTION__, data_size);
+
+ // Allocate a buffer to copy data into
+ std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer) {
+ strm.Printf("Error: Couldn't read allocation data");
+ strm.EOL();
+ return false;
+ }
- uint32_t dim_z = alloc->dimension.get()->dim_3;
- dim_z = dim_z == 0 ? 1 : dim_z;
+ // Calculate stride between rows as there may be padding at end of rows since
+ // allocated memory is 16-byte aligned
+ if (!alloc->stride.isValid()) {
+ if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
+ alloc->stride = 0;
+ else if (!JITAllocationStride(alloc, frame_ptr)) {
+ strm.Printf("Error: Couldn't calculate allocation row stride");
+ strm.EOL();
+ return false;
+ }
+ }
+ const uint32_t stride = *alloc->stride.get();
+ const uint32_t size = *alloc->size.get(); // Size of whole allocation
+ const uint32_t padding =
+ alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
+ if (log)
+ log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32
+ " bytes, padding %" PRIu32,
+ __FUNCTION__, stride, size, padding);
+
+ // Find dimensions used to index loops, so need to be non-zero
+ uint32_t dim_x = alloc->dimension.get()->dim_1;
+ dim_x = dim_x == 0 ? 1 : dim_x;
+
+ uint32_t dim_y = alloc->dimension.get()->dim_2;
+ dim_y = dim_y == 0 ? 1 : dim_y;
+
+ uint32_t dim_z = alloc->dimension.get()->dim_3;
+ dim_z = dim_z == 0 ? 1 : dim_z;
+
+ // Use data extractor to format output
+ const uint32_t archByteSize =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(),
+ archByteSize);
+
+ uint32_t offset = 0; // Offset in buffer to next element to be printed
+ uint32_t prev_row = 0; // Offset to the start of the previous row
+
+ // Iterate over allocation dimensions, printing results to user
+ strm.Printf("Data (X, Y, Z):");
+ for (uint32_t z = 0; z < dim_z; ++z) {
+ for (uint32_t y = 0; y < dim_y; ++y) {
+ // Use stride to index start of next row.
+ if (!(y == 0 && z == 0))
+ offset = prev_row + stride;
+ prev_row = offset;
+
+ // Print each element in the row individually
+ for (uint32_t x = 0; x < dim_x; ++x) {
+ strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
+ if ((type == Element::RS_TYPE_NONE) &&
+ (alloc->element.children.size() > 0) &&
+ (alloc->element.type_name != Element::GetFallbackStructName())) {
+ // Here we are dumping an Element of struct type.
+ // This is done using expression evaluation with the name of the
+ // struct type and pointer to element.
+
+ // Don't print the name of the resulting expression, since this will
+ // be '$[0-9]+'
+ DumpValueObjectOptions expr_options;
+ expr_options.SetHideName(true);
+
+ // Setup expression as derefrencing a pointer cast to element address.
+ char expr_char_buffer[jit_max_expr_size];
+ int chars_written =
+ snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
+ alloc->element.type_name.AsCString(),
+ *alloc->data_ptr.get() + offset);
- // Use data extractor to format output
- const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
- DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
+ if (chars_written < 0 || chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - error in snprintf().", __FUNCTION__);
+ continue;
+ }
- uint32_t offset = 0; // Offset in buffer to next element to be printed
- uint32_t prev_row = 0; // Offset to the start of the previous row
+ // Evaluate expression
+ ValueObjectSP expr_result;
+ GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer,
+ frame_ptr, expr_result);
- // Iterate over allocation dimensions, printing results to user
- strm.Printf("Data (X, Y, Z):");
- for (uint32_t z = 0; z < dim_z; ++z)
- {
- for (uint32_t y = 0; y < dim_y; ++y)
- {
- // Use stride to index start of next row.
- if (!(y == 0 && z == 0))
- offset = prev_row + stride;
- prev_row = offset;
-
- // Print each element in the row individually
- for (uint32_t x = 0; x < dim_x; ++x)
- {
- strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
- if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) &&
- (alloc->element.type_name != Element::GetFallbackStructName()))
- {
- // Here we are dumping an Element of struct type.
- // This is done using expression evaluation with the name of the struct type and pointer to element.
-
- // Don't print the name of the resulting expression, since this will be '$[0-9]+'
- DumpValueObjectOptions expr_options;
- expr_options.SetHideName(true);
-
- // Setup expression as derefrencing a pointer cast to element address.
- char expr_char_buffer[jit_max_expr_size];
- int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
- alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);
-
- if (chars_written < 0 || chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - error in snprintf().", __FUNCTION__);
- continue;
- }
-
- // Evaluate expression
- ValueObjectSP expr_result;
- GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result);
-
- // Print the results to our stream.
- expr_result->Dump(strm, expr_options);
- }
- else
- {
- alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
- }
- offset += data_size;
- }
+ // Print the results to our stream.
+ expr_result->Dump(strm, expr_options);
+ } else {
+ alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1,
+ LLDB_INVALID_ADDRESS, 0, 0);
}
+ offset += data_size;
+ }
}
- strm.EOL();
+ }
+ strm.EOL();
- return true;
+ return true;
}
-// Function recalculates all our cached information about allocations by jitting the
+// Function recalculates all our cached information about allocations by jitting
+// the
// RS runtime regarding each allocation we know about.
// Returns true if all allocations could be recomputed, false otherwise.
-bool
-RenderScriptRuntime::RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr)
-{
- bool success = true;
- for (auto &alloc : m_allocations)
- {
- // JIT current allocation information
- if (!RefreshAllocation(alloc.get(), frame_ptr))
- {
- strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32 "\n", alloc->id);
- success = false;
- }
- }
-
- if (success)
- strm.Printf("All allocations successfully recomputed");
- strm.EOL();
+bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
+ StackFrame *frame_ptr) {
+ bool success = true;
+ for (auto &alloc : m_allocations) {
+ // JIT current allocation information
+ if (!RefreshAllocation(alloc.get(), frame_ptr)) {
+ strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32
+ "\n",
+ alloc->id);
+ success = false;
+ }
+ }
+
+ if (success)
+ strm.Printf("All allocations successfully recomputed");
+ strm.EOL();
- return success;
+ return success;
}
// Prints information regarding currently loaded allocations.
// These details are gathered by jitting the runtime, which has as latency.
-// Index parameter specifies a single allocation ID to print, or a zero value to print them all
-void
-RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index)
-{
- strm.Printf("RenderScript Allocations:");
+// Index parameter specifies a single allocation ID to print, or a zero value to
+// print them all
+void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t index) {
+ strm.Printf("RenderScript Allocations:");
+ strm.EOL();
+ strm.IndentMore();
+
+ for (auto &alloc : m_allocations) {
+ // index will only be zero if we want to print all allocations
+ if (index != 0 && index != alloc->id)
+ continue;
+
+ // JIT current allocation information
+ if (alloc->shouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) {
+ strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32,
+ alloc->id);
+ strm.EOL();
+ continue;
+ }
+
+ strm.Printf("%" PRIu32 ":", alloc->id);
strm.EOL();
strm.IndentMore();
- for (auto &alloc : m_allocations)
- {
- // index will only be zero if we want to print all allocations
- if (index != 0 && index != alloc->id)
- continue;
-
- // JIT current allocation information
- if (alloc->shouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr))
- {
- strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32, alloc->id);
- strm.EOL();
- continue;
- }
-
- strm.Printf("%" PRIu32 ":", alloc->id);
- strm.EOL();
- strm.IndentMore();
-
- strm.Indent("Context: ");
- if (!alloc->context.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
-
- strm.Indent("Address: ");
- if (!alloc->address.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
-
- strm.Indent("Data pointer: ");
- if (!alloc->data_ptr.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
+ strm.Indent("Context: ");
+ if (!alloc->context.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
- strm.Indent("Dimensions: ");
- if (!alloc->dimension.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
- alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2, alloc->dimension.get()->dim_3);
+ strm.Indent("Address: ");
+ if (!alloc->address.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
- strm.Indent("Data Type: ");
- if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())
- strm.Printf("unknown\n");
- else
- {
- const int vector_size = *alloc->element.type_vec_size.get();
- Element::DataType type = *alloc->element.type.get();
-
- if (!alloc->element.type_name.IsEmpty())
- strm.Printf("%s\n", alloc->element.type_name.AsCString());
- else
- {
- // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
- if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
- type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
- sizeof(AllocationDetails::RsDataTypeToString[0])) ||
- vector_size > 4 || vector_size < 1)
- strm.Printf("invalid type\n");
- else
- strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
- [vector_size - 1]);
- }
- }
+ strm.Indent("Data pointer: ");
+ if (!alloc->data_ptr.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
- strm.Indent("Data Kind: ");
- if (!alloc->element.type_kind.isValid())
- strm.Printf("unknown\n");
+ strm.Indent("Dimensions: ");
+ if (!alloc->dimension.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
+ alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2,
+ alloc->dimension.get()->dim_3);
+
+ strm.Indent("Data Type: ");
+ if (!alloc->element.type.isValid() ||
+ !alloc->element.type_vec_size.isValid())
+ strm.Printf("unknown\n");
+ else {
+ const int vector_size = *alloc->element.type_vec_size.get();
+ Element::DataType type = *alloc->element.type.get();
+
+ if (!alloc->element.type_name.IsEmpty())
+ strm.Printf("%s\n", alloc->element.type_name.AsCString());
+ else {
+ // Enum value isn't monotonous, so doesn't always index
+ // RsDataTypeToString array
+ if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ type =
+ static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
+ Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
+ sizeof(AllocationDetails::RsDataTypeToString[0])) ||
+ vector_size > 4 || vector_size < 1)
+ strm.Printf("invalid type\n");
else
- {
- const Element::DataKind kind = *alloc->element.type_kind.get();
- if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
- strm.Printf("invalid kind\n");
- else
- strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
- }
-
- strm.EOL();
- strm.IndentLess();
+ strm.Printf(
+ "%s\n",
+ AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
+ [vector_size - 1]);
+ }
+ }
+
+ strm.Indent("Data Kind: ");
+ if (!alloc->element.type_kind.isValid())
+ strm.Printf("unknown\n");
+ else {
+ const Element::DataKind kind = *alloc->element.type_kind.get();
+ if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
+ strm.Printf("invalid kind\n");
+ else
+ strm.Printf(
+ "%s\n",
+ AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
}
+
+ strm.EOL();
strm.IndentLess();
+ }
+ strm.IndentLess();
}
// Set breakpoints on every kernel found in RS module
-void
-RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
-{
- for (const auto &kernel : rsmodule_sp->m_kernels)
- {
- // Don't set breakpoint on 'root' kernel
- if (strcmp(kernel.m_name.AsCString(), "root") == 0)
- continue;
+void RenderScriptRuntime::BreakOnModuleKernels(
+ const RSModuleDescriptorSP rsmodule_sp) {
+ for (const auto &kernel : rsmodule_sp->m_kernels) {
+ // Don't set breakpoint on 'root' kernel
+ if (strcmp(kernel.m_name.AsCString(), "root") == 0)
+ continue;
- CreateKernelBreakpoint(kernel.m_name);
- }
+ CreateKernelBreakpoint(kernel.m_name);
+ }
}
// Method is internally called by the 'kernel breakpoint all' command to
@@ -3175,1200 +3071,1191 @@ RenderScriptRuntime::BreakOnModuleKernel
//
// When do_break is true we want to enable this functionality.
// When do_break is false we want to disable it.
-void
-RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
-
- InitSearchFilter(target);
-
- // Set breakpoints on all the kernels
- if (do_break && !m_breakAllKernels)
- {
- m_breakAllKernels = true;
+void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ InitSearchFilter(target);
+
+ // Set breakpoints on all the kernels
+ if (do_break && !m_breakAllKernels) {
+ m_breakAllKernels = true;
- for (const auto &module : m_rsmodules)
- BreakOnModuleKernels(module);
+ for (const auto &module : m_rsmodules)
+ BreakOnModuleKernels(module);
- if (log)
- log->Printf("%s(True) - breakpoints set on all currently loaded kernels.", __FUNCTION__);
- }
- else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
- {
- m_breakAllKernels = false;
+ if (log)
+ log->Printf("%s(True) - breakpoints set on all currently loaded kernels.",
+ __FUNCTION__);
+ } else if (!do_break &&
+ m_breakAllKernels) // Breakpoints won't be set on any new kernels.
+ {
+ m_breakAllKernels = false;
- if (log)
- log->Printf("%s(False) - breakpoints no longer automatically set.", __FUNCTION__);
- }
+ if (log)
+ log->Printf("%s(False) - breakpoints no longer automatically set.",
+ __FUNCTION__);
+ }
}
// Given the name of a kernel this function creates a breakpoint using our
// own breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
-RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
-
- if (!m_filtersp)
- {
- if (log)
- log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__);
- return nullptr;
- }
+RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
- BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
-
- // Give RS breakpoints a specific name, so the user can manipulate them as a group.
- Error err;
- if (!bp->AddName("RenderScriptKernel", err) && log)
- log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString());
-
- return bp;
-}
+ if (!m_filtersp) {
+ if (log)
+ log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__);
+ return nullptr;
+ }
-// Given an expression for a variable this function tries to calculate the variable's value.
-// If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
+ BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
+ BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
+ m_filtersp, resolver_sp, false, false, false);
+
+ // Give RS breakpoints a specific name, so the user can manipulate them as a
+ // group.
+ Error err;
+ if (!bp->AddName("RenderScriptKernel", err) && log)
+ log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
+ err.AsCString());
+
+ return bp;
+}
+
+// Given an expression for a variable this function tries to calculate the
+// variable's value.
+// If this is possible it returns true and sets the uint64_t parameter to the
+// variables unsigned value.
// Otherwise function returns false.
-bool
-RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char *var_name, uint64_t &val)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- Error error;
- VariableSP var_sp;
-
- // Find variable in stack frame
- ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
- var_name, eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
- var_sp, error));
- if (!error.Success())
- {
- if (log)
- log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__, var_name);
- return false;
- }
-
- // Find the uint32_t value for the variable
- bool success = false;
- val = value_sp->GetValueAsUnsigned(0, &success);
- if (!success)
- {
- if (log)
- log->Printf("%s - error, couldn't parse '%s' as an uint32_t.", __FUNCTION__, var_name);
- return false;
- }
-
- return true;
-}
-
-// Function attempts to find the current coordinate of a kernel invocation by investigating the
-// values of frame variables in the .expand function. These coordinates are returned via the coord
-// array reference parameter. Returns true if the coordinates could be found, and false otherwise.
-bool
-RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Thread *thread_ptr)
-{
- static const std::string s_runtimeExpandSuffix(".expand");
- static const std::array<const char *, 3> s_runtimeCoordVars{{"rsIndex", "p->current.y", "p->current.z"}};
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!thread_ptr)
- {
- if (log)
- log->Printf("%s - Error, No thread pointer", __FUNCTION__);
-
- return false;
- }
-
- // Walk the call stack looking for a function whose name has the suffix '.expand'
- // and contains the variables we're looking for.
- for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i)
- {
- if (!thread_ptr->SetSelectedFrameByIndex(i))
- continue;
-
- StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
- if (!frame_sp)
- continue;
-
- // Find the function name
- const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
- const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString();
- if (!func_name_cstr)
- continue;
-
- if (log)
- log->Printf("%s - Inspecting function '%s'", __FUNCTION__, func_name_cstr);
-
- // Check if function name has .expand suffix
- std::string func_name(func_name_cstr);
- const int length_difference = func_name.length() - s_runtimeExpandSuffix.length();
- if (length_difference <= 0)
- continue;
-
- const int32_t has_expand_suffix = func_name.compare(length_difference,
- s_runtimeExpandSuffix.length(),
- s_runtimeExpandSuffix);
-
- if (has_expand_suffix != 0)
- continue;
-
- if (log)
- log->Printf("%s - Found .expand function '%s'", __FUNCTION__, func_name_cstr);
-
- // Get values for variables in .expand frame that tell us the current kernel invocation
- bool found_coord_variables = true;
- assert(s_runtimeCoordVars.size() == coord.size());
-
- for (uint32_t i = 0; i < coord.size(); ++i)
- {
- uint64_t value = 0;
- if (!GetFrameVarAsUnsigned(frame_sp, s_runtimeCoordVars[i], value))
- {
- found_coord_variables = false;
- break;
- }
- coord[i] = value;
- }
-
- if (found_coord_variables)
- return true;
- }
+bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp,
+ const char *var_name,
+ uint64_t &val) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ Error error;
+ VariableSP var_sp;
+
+ // Find variable in stack frame
+ ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
+ var_name, eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+ var_sp, error));
+ if (!error.Success()) {
+ if (log)
+ log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__,
+ var_name);
return false;
-}
-
-// Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
-// Baton parameter contains a pointer to the target coordinate we want to break on.
-// Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
-// Parameter 'break_id' is the id of the Breakpoint which made the callback.
-// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
-// a single logical breakpoint can have multiple addresses.
-bool
-RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, user_id_t break_id,
- user_id_t break_loc_id)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
-
- assert(baton && "Error: null baton in conditional kernel breakpoint callback");
-
- // Coordinate we want to stop on
- const uint32_t *target_coord = static_cast<const uint32_t *>(baton);
+ }
+ // Find the uint32_t value for the variable
+ bool success = false;
+ val = value_sp->GetValueAsUnsigned(0, &success);
+ if (!success) {
if (log)
- log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", __FUNCTION__, break_id,
- target_coord[0], target_coord[1], target_coord[2]);
-
- // Select current thread
- ExecutionContext context(ctx->exe_ctx_ref);
- Thread *thread_ptr = context.GetThreadPtr();
- assert(thread_ptr && "Null thread pointer");
+ log->Printf("%s - error, couldn't parse '%s' as an uint32_t.",
+ __FUNCTION__, var_name);
+ return false;
+ }
- // Find current kernel invocation from .expand frame variables
- RSCoordinate current_coord{}; // Zero initialise array
- if (!GetKernelCoordinate(current_coord, thread_ptr))
- {
- if (log)
- log->Printf("%s - Error, couldn't select .expand stack frame", __FUNCTION__);
- return false;
- }
+ return true;
+}
- if (log)
- log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0], current_coord[1],
- current_coord[2]);
+// Function attempts to find the current coordinate of a kernel invocation by
+// investigating the
+// values of frame variables in the .expand function. These coordinates are
+// returned via the coord
+// array reference parameter. Returns true if the coordinates could be found,
+// and false otherwise.
+bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
+ Thread *thread_ptr) {
+ static const std::string s_runtimeExpandSuffix(".expand");
+ static const std::array<const char *, 3> s_runtimeCoordVars{
+ {"rsIndex", "p->current.y", "p->current.z"}};
- // Check if the current kernel invocation coordinate matches our target coordinate
- if (current_coord[0] == target_coord[0] &&
- current_coord[1] == target_coord[1] &&
- current_coord[2] == target_coord[2])
- {
- if (log)
- log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0],
- current_coord[1], current_coord[2]);
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
- assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
- breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
- return true;
- }
+ if (!thread_ptr) {
+ if (log)
+ log->Printf("%s - Error, No thread pointer", __FUNCTION__);
- // No match on coordinate
return false;
-}
+ }
-// Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
-// Argument 'coords', represents a three dimensional coordinate which can be used to specify
-// a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
-void
-RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int, 3> coords,
- Error &error, TargetSP target)
-{
- if (!name)
- {
- error.SetErrorString("invalid kernel name");
- return;
- }
+ // Walk the call stack looking for a function whose name has the suffix
+ // '.expand'
+ // and contains the variables we're looking for.
+ for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) {
+ if (!thread_ptr->SetSelectedFrameByIndex(i))
+ continue;
+
+ StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
+ if (!frame_sp)
+ continue;
+
+ // Find the function name
+ const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
+ const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString();
+ if (!func_name_cstr)
+ continue;
- InitSearchFilter(target);
+ if (log)
+ log->Printf("%s - Inspecting function '%s'", __FUNCTION__,
+ func_name_cstr);
- ConstString kernel_name(name);
- BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
+ // Check if function name has .expand suffix
+ std::string func_name(func_name_cstr);
+ const int length_difference =
+ func_name.length() - s_runtimeExpandSuffix.length();
+ if (length_difference <= 0)
+ continue;
+
+ const int32_t has_expand_suffix =
+ func_name.compare(length_difference, s_runtimeExpandSuffix.length(),
+ s_runtimeExpandSuffix);
- // We have a conditional breakpoint on a specific coordinate
- if (coords[0] != -1)
- {
- strm.Printf("Conditional kernel breakpoint on coordinate %" PRId32 ", %" PRId32 ", %" PRId32,
- coords[0], coords[1], coords[2]);
- strm.EOL();
+ if (has_expand_suffix != 0)
+ continue;
- // Allocate memory for the baton, and copy over coordinate
- uint32_t *baton = new uint32_t[coords.size()];
- baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
+ if (log)
+ log->Printf("%s - Found .expand function '%s'", __FUNCTION__,
+ func_name_cstr);
- // Create a callback that will be invoked every time the breakpoint is hit.
- // The baton object passed to the handler is the target coordinate we want to break on.
- bp->SetCallback(KernelBreakpointHit, baton, true);
+ // Get values for variables in .expand frame that tell us the current kernel
+ // invocation
+ bool found_coord_variables = true;
+ assert(s_runtimeCoordVars.size() == coord.size());
+
+ for (uint32_t i = 0; i < coord.size(); ++i) {
+ uint64_t value = 0;
+ if (!GetFrameVarAsUnsigned(frame_sp, s_runtimeCoordVars[i], value)) {
+ found_coord_variables = false;
+ break;
+ }
+ coord[i] = value;
+ }
+
+ if (found_coord_variables)
+ return true;
+ }
+ return false;
+}
+
+// Callback when a kernel breakpoint hits and we're looking for a specific
+// coordinate.
+// Baton parameter contains a pointer to the target coordinate we want to break
+// on.
+// Function then checks the .expand frame for the current coordinate and breaks
+// to user if it matches.
+// Parameter 'break_id' is the id of the Breakpoint which made the callback.
+// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
+// a single logical breakpoint can have multiple addresses.
+bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
+ StoppointCallbackContext *ctx,
+ user_id_t break_id,
+ user_id_t break_loc_id) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ assert(baton &&
+ "Error: null baton in conditional kernel breakpoint callback");
+
+ // Coordinate we want to stop on
+ const uint32_t *target_coord = static_cast<const uint32_t *>(baton);
+
+ if (log)
+ log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32
+ ")",
+ __FUNCTION__, break_id, target_coord[0], target_coord[1],
+ target_coord[2]);
+
+ // Select current thread
+ ExecutionContext context(ctx->exe_ctx_ref);
+ Thread *thread_ptr = context.GetThreadPtr();
+ assert(thread_ptr && "Null thread pointer");
+
+ // Find current kernel invocation from .expand frame variables
+ RSCoordinate current_coord{}; // Zero initialise array
+ if (!GetKernelCoordinate(current_coord, thread_ptr)) {
+ if (log)
+ log->Printf("%s - Error, couldn't select .expand stack frame",
+ __FUNCTION__);
+ return false;
+ }
- // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
- m_conditional_breaks[bp->GetID()] = std::shared_ptr<uint32_t>(baton);
- }
+ if (log)
+ log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__,
+ current_coord[0], current_coord[1], current_coord[2]);
+
+ // Check if the current kernel invocation coordinate matches our target
+ // coordinate
+ if (current_coord[0] == target_coord[0] &&
+ current_coord[1] == target_coord[1] &&
+ current_coord[2] == target_coord[2]) {
+ if (log)
+ log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")",
+ __FUNCTION__, current_coord[0], current_coord[1],
+ current_coord[2]);
+
+ BreakpointSP breakpoint_sp =
+ context.GetTargetPtr()->GetBreakpointByID(break_id);
+ assert(breakpoint_sp != nullptr &&
+ "Error: Couldn't find breakpoint matching break id for callback");
+ breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint
+ // should only be hit once.
+ return true;
+ }
- if (bp)
- bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
+ // No match on coordinate
+ return false;
}
-void
-RenderScriptRuntime::DumpModules(Stream &strm) const
-{
- strm.Printf("RenderScript Modules:");
+// Tries to set a breakpoint on the start of a kernel, resolved using the kernel
+// name.
+// Argument 'coords', represents a three dimensional coordinate which can be
+// used to specify
+// a single kernel instance to break on. If this is set then we add a callback
+// to the breakpoint.
+void RenderScriptRuntime::PlaceBreakpointOnKernel(
+ Stream &strm, const char *name, const std::array<int, 3> coords,
+ Error &error, TargetSP target) {
+ if (!name) {
+ error.SetErrorString("invalid kernel name");
+ return;
+ }
+
+ InitSearchFilter(target);
+
+ ConstString kernel_name(name);
+ BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
+
+ // We have a conditional breakpoint on a specific coordinate
+ if (coords[0] != -1) {
+ strm.Printf("Conditional kernel breakpoint on coordinate %" PRId32
+ ", %" PRId32 ", %" PRId32,
+ coords[0], coords[1], coords[2]);
strm.EOL();
- strm.IndentMore();
- for (const auto &module : m_rsmodules)
- {
- module->Dump(strm);
- }
- strm.IndentLess();
+
+ // Allocate memory for the baton, and copy over coordinate
+ uint32_t *baton = new uint32_t[coords.size()];
+ baton[0] = coords[0];
+ baton[1] = coords[1];
+ baton[2] = coords[2];
+
+ // Create a callback that will be invoked every time the breakpoint is hit.
+ // The baton object passed to the handler is the target coordinate we want
+ // to break on.
+ bp->SetCallback(KernelBreakpointHit, baton, true);
+
+ // Store a shared pointer to the baton, so the memory will eventually be
+ // cleaned up after destruction
+ m_conditional_breaks[bp->GetID()] = std::shared_ptr<uint32_t>(baton);
+ }
+
+ if (bp)
+ bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
+}
+
+void RenderScriptRuntime::DumpModules(Stream &strm) const {
+ strm.Printf("RenderScript Modules:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules) {
+ module->Dump(strm);
+ }
+ strm.IndentLess();
}
RenderScriptRuntime::ScriptDetails *
-RenderScriptRuntime::LookUpScript(addr_t address, bool create)
-{
- for (const auto &s : m_scripts)
- {
- if (s->script.isValid())
- if (*s->script == address)
- return s.get();
- }
- if (create)
- {
- std::unique_ptr<ScriptDetails> s(new ScriptDetails);
- s->script = address;
- m_scripts.push_back(std::move(s));
- return m_scripts.back().get();
- }
- return nullptr;
+RenderScriptRuntime::LookUpScript(addr_t address, bool create) {
+ for (const auto &s : m_scripts) {
+ if (s->script.isValid())
+ if (*s->script == address)
+ return s.get();
+ }
+ if (create) {
+ std::unique_ptr<ScriptDetails> s(new ScriptDetails);
+ s->script = address;
+ m_scripts.push_back(std::move(s));
+ return m_scripts.back().get();
+ }
+ return nullptr;
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::LookUpAllocation(addr_t address)
-{
- for (const auto &a : m_allocations)
- {
- if (a->address.isValid())
- if (*a->address == address)
- return a.get();
- }
- return nullptr;
+RenderScriptRuntime::LookUpAllocation(addr_t address) {
+ for (const auto &a : m_allocations) {
+ if (a->address.isValid())
+ if (*a->address == address)
+ return a.get();
+ }
+ return nullptr;
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::CreateAllocation(addr_t address)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- // Remove any previous allocation which contains the same address
- auto it = m_allocations.begin();
- while (it != m_allocations.end())
- {
- if (*((*it)->address) == address)
- {
- if (log)
- log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64, __FUNCTION__, (*it)->id, address);
-
- it = m_allocations.erase(it);
- }
- else
- {
- it++;
- }
- }
-
- std::unique_ptr<AllocationDetails> a(new AllocationDetails);
- a->address = address;
- m_allocations.push_back(std::move(a));
- return m_allocations.back().get();
-}
+RenderScriptRuntime::CreateAllocation(addr_t address) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-void
-RSModuleDescriptor::Dump(Stream &strm) const
-{
- strm.Indent();
- m_module->GetFileSpec().Dump(&strm);
- if (m_module->GetNumCompileUnits())
- {
- strm.Indent("Debug info loaded.");
- }
- else
- {
- strm.Indent("Debug info does not exist.");
- }
- strm.EOL();
- strm.IndentMore();
- strm.Indent();
- strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
- strm.EOL();
- strm.IndentMore();
- for (const auto &global : m_globals)
- {
- global.Dump(strm);
- }
- strm.IndentLess();
- strm.Indent();
- strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
- strm.EOL();
- strm.IndentMore();
- for (const auto &kernel : m_kernels)
- {
- kernel.Dump(strm);
- }
- strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
+ // Remove any previous allocation which contains the same address
+ auto it = m_allocations.begin();
+ while (it != m_allocations.end()) {
+ if (*((*it)->address) == address) {
+ if (log)
+ log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64,
+ __FUNCTION__, (*it)->id, address);
+
+ it = m_allocations.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ std::unique_ptr<AllocationDetails> a(new AllocationDetails);
+ a->address = address;
+ m_allocations.push_back(std::move(a));
+ return m_allocations.back().get();
+}
+
+void RSModuleDescriptor::Dump(Stream &strm) const {
+ strm.Indent();
+ m_module->GetFileSpec().Dump(&strm);
+ if (m_module->GetNumCompileUnits()) {
+ strm.Indent("Debug info loaded.");
+ } else {
+ strm.Indent("Debug info does not exist.");
+ }
+ strm.EOL();
+ strm.IndentMore();
+ strm.Indent();
+ strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &global : m_globals) {
+ global.Dump(strm);
+ }
+ strm.IndentLess();
+ strm.Indent();
+ strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &kernel : m_kernels) {
+ kernel.Dump(strm);
+ }
+ strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &key_val : m_pragmas) {
+ strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
strm.EOL();
- strm.IndentMore();
- for (const auto &key_val : m_pragmas)
- {
- strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
- strm.EOL();
- }
- strm.IndentLess(4);
+ }
+ strm.IndentLess(4);
}
-void
-RSGlobalDescriptor::Dump(Stream &strm) const
-{
- strm.Indent(m_name.AsCString());
- VariableList var_list;
- m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
- if (var_list.GetSize() == 1)
- {
- auto var = var_list.GetVariableAtIndex(0);
- auto type = var->GetType();
- if (type)
- {
- strm.Printf(" - ");
- type->DumpTypeName(&strm);
- }
- else
- {
- strm.Printf(" - Unknown Type");
- }
+void RSGlobalDescriptor::Dump(Stream &strm) const {
+ strm.Indent(m_name.AsCString());
+ VariableList var_list;
+ m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
+ if (var_list.GetSize() == 1) {
+ auto var = var_list.GetVariableAtIndex(0);
+ auto type = var->GetType();
+ if (type) {
+ strm.Printf(" - ");
+ type->DumpTypeName(&strm);
+ } else {
+ strm.Printf(" - Unknown Type");
}
- else
- {
- strm.Printf(" - variable identified, but not found in binary");
- const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
- if (s)
- {
- strm.Printf(" (symbol exists) ");
- }
+ } else {
+ strm.Printf(" - variable identified, but not found in binary");
+ const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(
+ m_name, eSymbolTypeData);
+ if (s) {
+ strm.Printf(" (symbol exists) ");
}
+ }
- strm.EOL();
+ strm.EOL();
}
-void
-RSKernelDescriptor::Dump(Stream &strm) const
-{
- strm.Indent(m_name.AsCString());
- strm.EOL();
+void RSKernelDescriptor::Dump(Stream &strm) const {
+ strm.Indent(m_name.AsCString());
+ strm.EOL();
}
-class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript module dump",
- "Dumps renderscript specific information for all modules.", "renderscript module dump",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpModules(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript module dump",
+ "Dumps renderscript specific information for all modules.",
+ "renderscript module dump",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpModules(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with RenderScript modules.",
- nullptr)
- {
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript module",
+ "Commands that deal with RenderScript modules.",
+ nullptr) {
+ LoadSubCommand(
+ "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(
+ interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeModule() override = default;
+ ~CommandObjectRenderScriptRuntimeModule() override = default;
};
-class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel list",
- "Lists renderscript kernel names and associated script resources.",
- "renderscript kernel list", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeKernelList() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpKernels(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel list",
+ "Lists renderscript kernel names and associated script resources.",
+ "renderscript kernel list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeKernelList() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpKernels(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelBreakpointSet
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
- "Sets a breakpoint on a renderscript kernel.",
- "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
- m_options()
- {
+ CommandObjectRenderScriptRuntimeKernelBreakpointSet(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel breakpoint set",
+ "Sets a breakpoint on a renderscript kernel.",
+ "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'c':
+ if (!ParseCoordinate(option_arg))
+ error.SetErrorStringWithFormat(
+ "Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
+ option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
+ }
+
+ // -c takes an argument of the form 'num[,num][,num]'.
+ // Where 'id_cstr' is this argument with the whitespace trimmed.
+ // Missing coordinates are defaulted to zero.
+ bool ParseCoordinate(const char *id_cstr) {
+ RegularExpression regex;
+ RegularExpression::Match regex_match(3);
+
+ bool matched = false;
+ if (regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ else if (regex.Compile("^([0-9]+),([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ else if (regex.Compile("^([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ for (uint32_t i = 0; i < 3; i++) {
+ std::string group;
+ if (regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
+ m_coord[i] = (uint32_t)strtoul(group.c_str(), nullptr, 0);
+ else
+ m_coord[i] = 0;
+ }
+ return matched;
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ // -1 means the -c option hasn't been set
+ m_coord[0] = -1;
+ m_coord[1] = -1;
+ m_coord[2] = -1;
}
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options() {}
-
- ~CommandOptions() override = default;
-
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'c':
- if (!ParseCoordinate(option_arg))
- error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
- option_arg);
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
-
- // -c takes an argument of the form 'num[,num][,num]'.
- // Where 'id_cstr' is this argument with the whitespace trimmed.
- // Missing coordinates are defaulted to zero.
- bool
- ParseCoordinate(const char *id_cstr)
- {
- RegularExpression regex;
- RegularExpression::Match regex_match(3);
-
- bool matched = false;
- if (regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- else if (regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- else if (regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- for (uint32_t i = 0; i < 3; i++)
- {
- std::string group;
- if (regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
- m_coord[i] = (uint32_t)strtoul(group.c_str(), nullptr, 0);
- else
- m_coord[i] = 0;
- }
- return matched;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- // -1 means the -c option hasn't been set
- m_coord[0] = -1;
- m_coord[1] = -1;
- m_coord[2] = -1;
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
- static OptionDefinition g_option_table[];
- std::array<int, 3> m_coord;
- };
+ static OptionDefinition g_option_table[];
+ std::array<int, 3> m_coord;
+ };
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc < 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 1 argument of kernel name, and an optional coordinate.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
- Error error;
- runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
- error, m_exe_ctx.GetTargetSP());
-
- if (error.Success())
- {
- result.AppendMessage("Breakpoint(s) created");
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- result.SetStatus(eReturnStatusFailed);
- result.AppendErrorWithFormat("Error: %s", error.AsCString());
- return false;
+ Error error;
+ runtime->PlaceBreakpointOnKernel(
+ result.GetOutputStream(), command.GetArgumentAtIndex(0),
+ m_options.m_coord, error, m_exe_ctx.GetTargetSP());
+
+ if (error.Success()) {
+ result.AppendMessage("Breakpoint(s) created");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
}
+ result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Error: %s", error.AsCString());
+ return false;
+ }
private:
- CommandOptions m_options;
+ CommandOptions m_options;
};
-OptionDefinition CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue,
- "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
- "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
- "Any unset dimensions will be defaulted to zero."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+OptionDefinition CommandObjectRenderScriptRuntimeKernelBreakpointSet::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "coordinate", 'c',
+ OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue,
+ "Set a breakpoint on a single invocation of the kernel with specified "
+ "coordinate.\n"
+ "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
+ "integers representing kernel dimensions. "
+ "Any unset dimensions will be defaulted to zero."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelBreakpointAll
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript kernel breakpoint all",
- "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
- "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
- "but does not remove currently set breakpoints.",
- "renderscript kernel breakpoint all <enable/disable>",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
- {
+ CommandObjectRenderScriptRuntimeKernelBreakpointAll(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel breakpoint all",
+ "Automatically sets a breakpoint on all renderscript kernels that "
+ "are or will be loaded.\n"
+ "Disabling option means breakpoints will no longer be set on any "
+ "kernels loaded in the future, "
+ "but does not remove currently set breakpoints.",
+ "renderscript kernel breakpoint all <enable/disable>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {}
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 1) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ bool do_break = false;
+ const char *argument = command.GetArgumentAtIndex(0);
+ if (strcmp(argument, "enable") == 0) {
+ do_break = true;
+ result.AppendMessage("Breakpoints will be set on all kernels.");
+ } else if (strcmp(argument, "disable") == 0) {
+ do_break = false;
+ result.AppendMessage("Breakpoints will not be set on any new kernels.");
+ } else {
+ result.AppendErrorWithFormat(
+ "Argument must be either 'enable' or 'disable'");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+ runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
- bool do_break = false;
- const char *argument = command.GetArgumentAtIndex(0);
- if (strcmp(argument, "enable") == 0)
- {
- do_break = true;
- result.AppendMessage("Breakpoints will be set on all kernels.");
- }
- else if (strcmp(argument, "disable") == 0)
- {
- do_break = false;
- result.AppendMessage("Breakpoints will not be set on any new kernels.");
- }
- else
- {
- result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeKernelCoordinate : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelCoordinate
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelCoordinate(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel coordinate",
- "Shows the (x,y,z) coordinate of the current kernel invocation.",
- "renderscript kernel coordinate",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RSCoordinate coord{}; // Zero initialize array
- bool success = RenderScriptRuntime::GetKernelCoordinate(coord, m_exe_ctx.GetThreadPtr());
- Stream &stream = result.GetOutputStream();
-
- if (success)
- {
- stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", coord[0], coord[1], coord[2]);
- stream.EOL();
- result.SetStatus(eReturnStatusSuccessFinishResult);
- }
- else
- {
- stream.Printf("Error: Coordinate could not be found.");
- stream.EOL();
- result.SetStatus(eReturnStatusFailed);
- }
- return true;
+ CommandObjectRenderScriptRuntimeKernelCoordinate(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel coordinate",
+ "Shows the (x,y,z) coordinate of the current kernel invocation.",
+ "renderscript kernel coordinate",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {}
+
+ ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RSCoordinate coord{}; // Zero initialize array
+ bool success = RenderScriptRuntime::GetKernelCoordinate(
+ coord, m_exe_ctx.GetThreadPtr());
+ Stream &stream = result.GetOutputStream();
+
+ if (success) {
+ stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")",
+ coord[0], coord[1], coord[2]);
+ stream.EOL();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ } else {
+ stream.Printf("Error: Coordinate could not be found.");
+ stream.EOL();
+ result.SetStatus(eReturnStatusFailed);
}
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeKernelBreakpoint
+ : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript kernel",
- "Commands that generate breakpoints on renderscript kernels.", nullptr)
- {
- LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
- LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeKernelBreakpoint(
+ CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript kernel",
+ "Commands that generate breakpoints on renderscript kernels.",
+ nullptr) {
+ LoadSubCommand(
+ "set",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(
+ interpreter)));
+ LoadSubCommand(
+ "all",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(
+ interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
+ ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
};
-class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with RenderScript kernels.",
- nullptr)
- {
- LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
- LoadSubCommand("coordinate",
- CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
- LoadSubCommand("breakpoint",
- CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript kernel",
+ "Commands that deal with RenderScript kernels.",
+ nullptr) {
+ LoadSubCommand(
+ "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(
+ interpreter)));
+ LoadSubCommand(
+ "coordinate",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
+ LoadSubCommand(
+ "breakpoint",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeKernel() override = default;
+ ~CommandObjectRenderScriptRuntimeKernel() override = default;
};
-class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript context dump", "Dumps renderscript context information.",
- "renderscript context dump", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeContextDump() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpContexts(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript context dump",
+ "Dumps renderscript context information.",
+ "renderscript context dump",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeContextDump() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpContexts(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with RenderScript contexts.",
- nullptr)
- {
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript context",
+ "Commands that deal with RenderScript contexts.",
+ nullptr) {
+ LoadSubCommand(
+ "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(
+ interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeContext() override = default;
+ ~CommandObjectRenderScriptRuntimeContext() override = default;
};
-class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationDump
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation dump",
- "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched),
- m_options()
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
- }
-
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options() {}
-
- ~CommandOptions() override = default;
-
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'f':
- m_outfile.SetFile(option_arg, true);
- if (m_outfile.Exists())
- {
- m_outfile.Clear();
- error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
- }
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- m_outfile.Clear();
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
-
- static OptionDefinition g_option_table[];
- FileSpec m_outfile;
- };
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc < 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- Stream *output_strm = nullptr;
- StreamFile outfile_stream;
- const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
- if (outfile_spec)
- {
- // Open output file
- char path[256];
- outfile_spec.GetPath(path, sizeof(path));
- if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
- {
- output_strm = &outfile_stream;
- result.GetOutputStream().Printf("Results written to '%s'", path);
- result.GetOutputStream().EOL();
- }
- else
- {
- result.AppendErrorWithFormat("Couldn't open file '%s'", path);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- else
- output_strm = &result.GetOutputStream();
-
- assert(output_strm != nullptr);
- bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
+ CommandObjectRenderScriptRuntimeAllocationDump(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation dump",
+ "Displays the contents of a particular allocation",
+ "renderscript allocation dump <ID>",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'f':
+ m_outfile.SetFile(option_arg, true);
+ if (m_outfile.Exists()) {
+ m_outfile.Clear();
+ error.SetErrorStringWithFormat("file already exists: '%s'",
+ option_arg);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_outfile.Clear();
+ }
+
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
+
+ static OptionDefinition g_option_table[];
+ FileSpec m_outfile;
+ };
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1) {
+ result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
+ "As well as an optional -f argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream *output_strm = nullptr;
+ StreamFile outfile_stream;
+ const FileSpec &outfile_spec =
+ m_options.m_outfile; // Dump allocation to file instead
+ if (outfile_spec) {
+ // Open output file
+ char path[256];
+ outfile_spec.GetPath(path, sizeof(path));
+ if (outfile_stream.GetFile()
+ .Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)
+ .Success()) {
+ output_strm = &outfile_stream;
+ result.GetOutputStream().Printf("Results written to '%s'", path);
+ result.GetOutputStream().EOL();
+ } else {
+ result.AppendErrorWithFormat("Couldn't open file '%s'", path);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ } else
+ output_strm = &result.GetOutputStream();
+
+ assert(output_strm != nullptr);
+ bool success =
+ runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
- return true;
- }
+ return true;
+ }
private:
- CommandOptions m_options;
+ CommandOptions m_options;
};
-OptionDefinition CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename,
- "Print results to specified file instead of command line."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+OptionDefinition CommandObjectRenderScriptRuntimeAllocationDump::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeFilename,
+ "Print results to specified file instead of command line."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationList
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation list",
- "List renderscript allocations and their information.", "renderscript allocation list",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched),
- m_options()
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
- }
-
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options(), m_id(0) {}
-
- ~CommandOptions() override = default;
-
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'i':
- bool success;
- m_id = StringConvert::ToUInt32(option_arg, 0, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- m_id = 0;
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
-
- static OptionDefinition g_option_table[];
- uint32_t m_id;
- };
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
- runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_id);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ CommandObjectRenderScriptRuntimeAllocationList(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript allocation list",
+ "List renderscript allocations and their information.",
+ "renderscript allocation list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_id(0) {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'i':
+ bool success;
+ m_id = StringConvert::ToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%c'", short_option);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_id = 0;
+ }
+
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
+
+ static OptionDefinition g_option_table[];
+ uint32_t m_id;
+ };
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+ runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(),
+ m_options.m_id);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
private:
- CommandOptions m_options;
+ CommandOptions m_options;
};
-OptionDefinition CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex,
- "Only show details of a single allocation with specified id."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+OptionDefinition CommandObjectRenderScriptRuntimeAllocationList::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeIndex,
+ "Only show details of a single allocation with specified id."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationLoad
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript allocation load", "Loads renderscript allocation contents from a file.",
- "renderscript allocation load <ID> <filename>", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 2)
- {
- result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char *filename = command.GetArgumentAtIndex(1);
- bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
+ CommandObjectRenderScriptRuntimeAllocationLoad(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript allocation load",
+ "Loads renderscript allocation contents from a file.",
+ "renderscript allocation load <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 2 arguments, an allocation ID and filename to read from.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ const char *filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->LoadAllocation(result.GetOutputStream(), id,
+ filename, m_exe_ctx.GetFramePtr());
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
- return true;
- }
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationSave
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript allocation save", "Write renderscript allocation contents to a file.",
- "renderscript allocation save <ID> <filename>", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 2)
- {
- result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
+ CommandObjectRenderScriptRuntimeAllocationSave(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation save",
+ "Write renderscript allocation contents to a file.",
+ "renderscript allocation save <ID> <filename>",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 2 arguments, an allocation ID and filename to read from.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ const char *filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->SaveAllocation(result.GetOutputStream(), id,
+ filename, m_exe_ctx.GetFramePtr());
- const char *filename = command.GetArgumentAtIndex(1);
- bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
-
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
- return true;
- }
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeAllocationRefresh : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationRefresh
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationRefresh(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation refresh",
- "Recomputes the details of all allocations.", "renderscript allocation refresh",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr());
-
- if (success)
- {
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- else
- {
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
+ CommandObjectRenderScriptRuntimeAllocationRefresh(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation refresh",
+ "Recomputes the details of all allocations.",
+ "renderscript allocation refresh",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(),
+ m_exe_ctx.GetFramePtr());
+
+ if (success) {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ } else {
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
+ }
};
-class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeAllocation
+ : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript allocation",
- "Commands that deal with RenderScript allocations.", nullptr)
- {
- LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
- LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
- LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
- LoadSubCommand("refresh", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript allocation",
+ "Commands that deal with RenderScript allocations.", nullptr) {
+ LoadSubCommand(
+ "list",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
+ LoadSubCommand(
+ "dump",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
+ LoadSubCommand(
+ "save",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
+ LoadSubCommand(
+ "load",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
+ LoadSubCommand(
+ "refresh",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(
+ interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeAllocation() override = default;
+ ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};
-class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript status", "Displays current RenderScript runtime status.",
- "renderscript status", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeStatus() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->Status(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript status",
+ "Displays current RenderScript runtime status.",
+ "renderscript status",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeStatus() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->Status(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntime : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript", "Commands for operating on the RenderScript runtime.",
- "renderscript <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
- LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
- LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
- LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
- LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
- }
+ CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript",
+ "Commands for operating on the RenderScript runtime.",
+ "renderscript <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "module", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeModule(interpreter)));
+ LoadSubCommand(
+ "status", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeStatus(interpreter)));
+ LoadSubCommand(
+ "kernel", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernel(interpreter)));
+ LoadSubCommand("context",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(
+ interpreter)));
+ LoadSubCommand(
+ "allocation",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
+ }
- ~CommandObjectRenderScriptRuntime() override = default;
+ ~CommandObjectRenderScriptRuntime() override = default;
};
-void
-RenderScriptRuntime::Initiate()
-{
- assert(!m_initiated);
-}
+void RenderScriptRuntime::Initiate() { assert(!m_initiated); }
RenderScriptRuntime::RenderScriptRuntime(Process *process)
- : lldb_private::CPPLanguageRuntime(process),
- m_initiated(false),
- m_debuggerPresentFlagged(false),
- m_breakAllKernels(false),
- m_ir_passes(nullptr)
-{
- ModulesDidLoad(process->GetTarget().GetImages());
+ : lldb_private::CPPLanguageRuntime(process), m_initiated(false),
+ m_debuggerPresentFlagged(false), m_breakAllKernels(false),
+ m_ir_passes(nullptr) {
+ ModulesDidLoad(process->GetTarget().GetImages());
}
-lldb::CommandObjectSP
-RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter &interpreter)
-{
- return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
+lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject(
+ lldb_private::CommandInterpreter &interpreter) {
+ return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
}
RenderScriptRuntime::~RenderScriptRuntime() = default;
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h Tue Sep 6 15:57:50 2016
@@ -26,10 +26,8 @@
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
+namespace lldb_private {
+namespace lldb_renderscript {
typedef uint32_t RSSlot;
class RSModuleDescriptor;
@@ -44,383 +42,330 @@ typedef std::array<uint32_t, 3> RSCoordi
// Breakpoint Resolvers decide where a breakpoint is placed,
// so having our own allows us to limit the search scope to RS kernel modules.
// As well as check for .expand kernels as a fallback.
-class RSBreakpointResolver : public BreakpointResolver
-{
+class RSBreakpointResolver : public BreakpointResolver {
public:
- RSBreakpointResolver(Breakpoint *bkpt, ConstString name)
- : BreakpointResolver(bkpt, BreakpointResolver::NameResolver), m_kernel_name(name)
- {
- }
-
- void
- GetDescription(Stream *strm) override
- {
- if (strm)
- strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
- }
-
- void
- Dump(Stream *s) const override
- {
- }
-
- Searcher::CallbackReturn
- SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) override;
-
- Searcher::Depth
- GetDepth() override
- {
- return Searcher::eDepthModule;
- }
-
- lldb::BreakpointResolverSP
- CopyForBreakpoint(Breakpoint &breakpoint) override
- {
- lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
- return ret_sp;
- }
+ RSBreakpointResolver(Breakpoint *bkpt, ConstString name)
+ : BreakpointResolver(bkpt, BreakpointResolver::NameResolver),
+ m_kernel_name(name) {}
+
+ void GetDescription(Stream *strm) override {
+ if (strm)
+ strm->Printf("RenderScript kernel breakpoint for '%s'",
+ m_kernel_name.AsCString());
+ }
+
+ void Dump(Stream *s) const override {}
+
+ Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *addr,
+ bool containing) override;
+
+ Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
+
+ lldb::BreakpointResolverSP
+ CopyForBreakpoint(Breakpoint &breakpoint) override {
+ lldb::BreakpointResolverSP ret_sp(
+ new RSBreakpointResolver(&breakpoint, m_kernel_name));
+ return ret_sp;
+ }
protected:
- ConstString m_kernel_name;
+ ConstString m_kernel_name;
};
-struct RSKernelDescriptor
-{
+struct RSKernelDescriptor {
public:
- RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
- : m_module(module), m_name(name), m_slot(slot)
- {
- }
-
- void
- Dump(Stream &strm) const;
-
- const RSModuleDescriptor *m_module;
- ConstString m_name;
- RSSlot m_slot;
+ RSKernelDescriptor(const RSModuleDescriptor *module, const char *name,
+ uint32_t slot)
+ : m_module(module), m_name(name), m_slot(slot) {}
+
+ void Dump(Stream &strm) const;
+
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
+ RSSlot m_slot;
};
-struct RSGlobalDescriptor
-{
+struct RSGlobalDescriptor {
public:
- RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name) : m_module(module), m_name(name) {}
+ RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name)
+ : m_module(module), m_name(name) {}
- void
- Dump(Stream &strm) const;
+ void Dump(Stream &strm) const;
- const RSModuleDescriptor *m_module;
- ConstString m_name;
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
};
-class RSModuleDescriptor
-{
+class RSModuleDescriptor {
public:
- RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {}
+ RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {}
- ~RSModuleDescriptor() = default;
+ ~RSModuleDescriptor() = default;
- bool
- ParseRSInfo();
+ bool ParseRSInfo();
- void
- Dump(Stream &strm) const;
+ void Dump(Stream &strm) const;
- const lldb::ModuleSP m_module;
- std::vector<RSKernelDescriptor> m_kernels;
- std::vector<RSGlobalDescriptor> m_globals;
- std::map<std::string, std::string> m_pragmas;
- std::string m_resname;
+ const lldb::ModuleSP m_module;
+ std::vector<RSKernelDescriptor> m_kernels;
+ std::vector<RSGlobalDescriptor> m_globals;
+ std::map<std::string, std::string> m_pragmas;
+ std::string m_resname;
};
} // namespace lldb_renderscript
-class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
-{
+class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime {
public:
- enum ModuleKind
- {
- eModuleKindIgnored,
- eModuleKindLibRS,
- eModuleKindDriver,
- eModuleKindImpl,
- eModuleKindKernelObj
- };
+ enum ModuleKind {
+ eModuleKindIgnored,
+ eModuleKindLibRS,
+ eModuleKindDriver,
+ eModuleKindImpl,
+ eModuleKindKernelObj
+ };
- ~RenderScriptRuntime() override;
+ ~RenderScriptRuntime() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- static void
- Terminate();
+ static void Terminate();
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
- static lldb::CommandObjectSP
- GetCommandObject(CommandInterpreter &interpreter);
+ static lldb::CommandObjectSP
+ GetCommandObject(CommandInterpreter &interpreter);
- static lldb_private::ConstString
- GetPluginNameStatic();
+ static lldb_private::ConstString GetPluginNameStatic();
- static bool
- IsRenderScriptModule(const lldb::ModuleSP &module_sp);
+ static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp);
- static ModuleKind
- GetModuleKind(const lldb::ModuleSP &module_sp);
+ static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp);
- static void
- ModulesDidLoad(const lldb::ProcessSP &process_sp, const ModuleList &module_list);
+ static void ModulesDidLoad(const lldb::ProcessSP &process_sp,
+ const ModuleList &module_list);
- bool
- IsVTableName(const char *name) override;
+ bool IsVTableName(const char *name) override;
- bool
- GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type) override;
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- TypeAndOrName
- FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
- bool
- CouldHaveDynamicValue(ValueObject &in_value) override;
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override;
- bool
- LoadModule(const lldb::ModuleSP &module_sp);
+ bool LoadModule(const lldb::ModuleSP &module_sp);
- void
- DumpModules(Stream &strm) const;
+ void DumpModules(Stream &strm) const;
- void
- DumpContexts(Stream &strm) const;
+ void DumpContexts(Stream &strm) const;
- void
- DumpKernels(Stream &strm) const;
+ void DumpKernels(Stream &strm) const;
- bool
- DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id);
+ bool DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id);
- void
- ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index);
+ void ListAllocations(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t index);
- bool
- RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr);
+ bool RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr);
- void
- PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int, 3> coords, Error &error,
- lldb::TargetSP target);
+ void PlaceBreakpointOnKernel(Stream &strm, const char *name,
+ const std::array<int, 3> coords, Error &error,
+ lldb::TargetSP target);
- void
- SetBreakAllKernels(bool do_break, lldb::TargetSP target);
+ void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
- void
- Status(Stream &strm) const;
+ void Status(Stream &strm) const;
- void
- ModulesDidLoad(const ModuleList &module_list) override;
+ void ModulesDidLoad(const ModuleList &module_list) override;
- bool
- LoadAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr);
+ bool LoadAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename, StackFrame *frame_ptr);
- bool
- SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr);
+ bool SaveAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename, StackFrame *frame_ptr);
- void
- Update();
+ void Update();
- void
- Initiate();
+ void Initiate();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
- uint32_t
- GetPluginVersion() override;
+ uint32_t GetPluginVersion() override;
- static bool
- GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord, Thread *thread_ptr);
+ static bool GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord,
+ Thread *thread_ptr);
protected:
- struct ScriptDetails;
- struct AllocationDetails;
- struct Element;
-
- void
- InitSearchFilter(lldb::TargetSP target)
- {
- if (!m_filtersp)
- m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
- }
-
- void
- FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
-
- void
- LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
-
- bool
- RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr);
-
- bool
- EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result);
-
- lldb::BreakpointSP
- CreateKernelBreakpoint(const ConstString &name);
-
- void
- BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
-
- struct RuntimeHook;
- typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook *hook_info,
- ExecutionContext &context); // Please do this!
-
- struct HookDefn
- {
- const char *name;
- const char *symbol_name_m32; // mangled name for the 32 bit architectures
- const char *symbol_name_m64; // mangled name for the 64 bit archs
- uint32_t version;
- ModuleKind kind;
- CaptureStateFn grabber;
- };
-
- struct RuntimeHook
- {
- lldb::addr_t address;
- const HookDefn *defn;
- lldb::BreakpointSP bp_sp;
- };
-
- typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
-
- lldb::ModuleSP m_libRS;
- lldb::ModuleSP m_libRSDriver;
- lldb::ModuleSP m_libRSCpuRef;
- std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
-
- std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
- std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
-
- std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
- std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
- std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks;
-
- lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
-
- bool m_initiated;
- bool m_debuggerPresentFlagged;
- bool m_breakAllKernels;
- static const HookDefn s_runtimeHookDefns[];
- static const size_t s_runtimeHookCount;
- LLVMUserExpression::IRPasses *m_ir_passes;
+ struct ScriptDetails;
+ struct AllocationDetails;
+ struct Element;
+
+ void InitSearchFilter(lldb::TargetSP target) {
+ if (!m_filtersp)
+ m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
+ }
+
+ void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
+
+ void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+
+ bool RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr);
+
+ bool EvalRSExpression(const char *expression, StackFrame *frame_ptr,
+ uint64_t *result);
+
+ lldb::BreakpointSP CreateKernelBreakpoint(const ConstString &name);
+
+ void BreakOnModuleKernels(
+ const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
+
+ struct RuntimeHook;
+ typedef void (RenderScriptRuntime::*CaptureStateFn)(
+ RuntimeHook *hook_info,
+ ExecutionContext &context); // Please do this!
+
+ struct HookDefn {
+ const char *name;
+ const char *symbol_name_m32; // mangled name for the 32 bit architectures
+ const char *symbol_name_m64; // mangled name for the 64 bit archs
+ uint32_t version;
+ ModuleKind kind;
+ CaptureStateFn grabber;
+ };
+
+ struct RuntimeHook {
+ lldb::addr_t address;
+ const HookDefn *defn;
+ lldb::BreakpointSP bp_sp;
+ };
+
+ typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
+
+ lldb::ModuleSP m_libRS;
+ lldb::ModuleSP m_libRSDriver;
+ lldb::ModuleSP m_libRSCpuRef;
+ std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
+
+ std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
+ std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
+
+ std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP>
+ m_scriptMappings;
+ std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
+ std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks;
+
+ lldb::SearchFilterSP
+ m_filtersp; // Needed to create breakpoints through Target API
+
+ bool m_initiated;
+ bool m_debuggerPresentFlagged;
+ bool m_breakAllKernels;
+ static const HookDefn s_runtimeHookDefns[];
+ static const size_t s_runtimeHookCount;
+ LLVMUserExpression::IRPasses *m_ir_passes;
private:
- RenderScriptRuntime(Process *process); // Call CreateInstance instead.
+ RenderScriptRuntime(Process *process); // Call CreateInstance instead.
- static bool
- HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+ static bool HookCallback(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
- static bool
- KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
+ static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
- void
- HookCallback(RuntimeHook *hook_info, ExecutionContext &context);
+ void HookCallback(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureAllocationDestroy(RuntimeHook *hook_info,
+ ExecutionContext &context);
- void
- CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info,
+ ExecutionContext &context);
- AllocationDetails *
- FindAllocByID(Stream &strm, const uint32_t alloc_id);
+ AllocationDetails *FindAllocByID(Stream &strm, const uint32_t alloc_id);
- std::shared_ptr<uint8_t>
- GetAllocationData(AllocationDetails *allocation, StackFrame *frame_ptr);
+ std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails *allocation,
+ StackFrame *frame_ptr);
- void
- SetElementSize(Element &elem);
+ void SetElementSize(Element &elem);
- static bool
- GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char *var_name, uint64_t &val);
+ static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP,
+ const char *var_name, uint64_t &val);
- void
- FindStructTypeName(Element &elem, StackFrame *frame_ptr);
+ void FindStructTypeName(Element &elem, StackFrame *frame_ptr);
- size_t
- PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element &elem);
+ size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer,
+ size_t offset, const Element &elem);
- size_t
- CalculateElementHeaderSize(const Element &elem);
+ size_t CalculateElementHeaderSize(const Element &elem);
- //
- // Helper functions for jitting the runtime
- //
+ //
+ // Helper functions for jitting the runtime
+ //
- bool
- JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr,
- uint32_t x = 0, uint32_t y = 0, uint32_t z = 0);
+ bool JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr,
+ uint32_t x = 0, uint32_t y = 0, uint32_t z = 0);
- bool
- JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr);
+ bool JITElementPacked(Element &elem, const lldb::addr_t context,
+ StackFrame *frame_ptr);
- bool
- JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr);
+ bool JITSubelements(Element &elem, const lldb::addr_t context,
+ StackFrame *frame_ptr);
- bool
- JITAllocationStride(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITAllocationStride(AllocationDetails *allocation,
+ StackFrame *frame_ptr);
- // Search for a script detail object using a target address.
- // If a script does not currently exist this function will return nullptr.
- // If 'create' is true and there is no previous script with this address,
- // then a new Script detail object will be created for this address and returned.
- ScriptDetails *
- LookUpScript(lldb::addr_t address, bool create);
+ // Search for a script detail object using a target address.
+ // If a script does not currently exist this function will return nullptr.
+ // If 'create' is true and there is no previous script with this address,
+ // then a new Script detail object will be created for this address and
+ // returned.
+ ScriptDetails *LookUpScript(lldb::addr_t address, bool create);
- // Search for a previously saved allocation detail object using a target address.
- // If an allocation does not exist for this address then nullptr will be returned.
- AllocationDetails *
- LookUpAllocation(lldb::addr_t address);
+ // Search for a previously saved allocation detail object using a target
+ // address.
+ // If an allocation does not exist for this address then nullptr will be
+ // returned.
+ AllocationDetails *LookUpAllocation(lldb::addr_t address);
- // Creates a new allocation with the specified address assigning a new ID and removes
- // any previous stored allocation which has the same address.
- AllocationDetails *
- CreateAllocation(lldb::addr_t address);
+ // Creates a new allocation with the specified address assigning a new ID and
+ // removes
+ // any previous stored allocation which has the same address.
+ AllocationDetails *CreateAllocation(lldb::addr_t address);
- bool
- GetOverrideExprOptions(clang::TargetOptions &prototype) override;
+ bool GetOverrideExprOptions(clang::TargetOptions &prototype) override;
- bool
- GetIRPasses(LLVMUserExpression::IRPasses &passes) override;
+ bool GetIRPasses(LLVMUserExpression::IRPasses &passes) override;
};
} // namespace lldb_private
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp Tue Sep 6 15:57:50 2016
@@ -28,258 +28,271 @@
#include "lldb/Target/Process.h"
using namespace lldb_private;
-namespace
-{
+namespace {
-bool
-isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst)
-{
- // TODO get the list of renderscript modules from lldb and check if
- // this llvm::Module calls into any of them.
- (void)module;
- const auto func_name = call_inst->getCalledFunction()->getName();
- if (func_name.startswith("llvm") || func_name.startswith("lldb"))
- return false;
+bool isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst) {
+ // TODO get the list of renderscript modules from lldb and check if
+ // this llvm::Module calls into any of them.
+ (void)module;
+ const auto func_name = call_inst->getCalledFunction()->getName();
+ if (func_name.startswith("llvm") || func_name.startswith("lldb"))
+ return false;
- if (call_inst->getCalledFunction()->isIntrinsic())
- return false;
+ if (call_inst->getCalledFunction()->isIntrinsic())
+ return false;
- return true;
+ return true;
}
-bool
-isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst)
-{
- // i686 and x86_64 returns for large vectors in the RenderScript API are not handled as normal
- // register pairs, but as a hidden sret type. This is not reflected in the debug info or mangled
- // symbol name, and the android ABI for x86 and x86_64, (as well as the emulators) specifies there is
- // no AVX, so bcc generates an sret function because we cannot natively return 256 bit vectors.
- // This function simply checks whether a function has a > 128bit return type. It is perhaps an
- // unreliable heuristic, and relies on bcc not generating AVX code, so if the android ABI one day
- // provides for AVX, this function may go out of fashion.
- (void)module;
- if (!call_inst || !call_inst->getCalledFunction())
- return false;
+bool isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst) {
+ // i686 and x86_64 returns for large vectors in the RenderScript API are not
+ // handled as normal
+ // register pairs, but as a hidden sret type. This is not reflected in the
+ // debug info or mangled
+ // symbol name, and the android ABI for x86 and x86_64, (as well as the
+ // emulators) specifies there is
+ // no AVX, so bcc generates an sret function because we cannot natively return
+ // 256 bit vectors.
+ // This function simply checks whether a function has a > 128bit return type.
+ // It is perhaps an
+ // unreliable heuristic, and relies on bcc not generating AVX code, so if the
+ // android ABI one day
+ // provides for AVX, this function may go out of fashion.
+ (void)module;
+ if (!call_inst || !call_inst->getCalledFunction())
+ return false;
- return call_inst->getCalledFunction()->getReturnType()->getPrimitiveSizeInBits() > 128;
+ return call_inst->getCalledFunction()
+ ->getReturnType()
+ ->getPrimitiveSizeInBits() > 128;
}
-bool
-isRSAllocationPtrTy(const llvm::Type *type)
-{
- if (!type->isPointerTy())
- return false;
- auto ptr_type = type->getPointerElementType();
+bool isRSAllocationPtrTy(const llvm::Type *type) {
+ if (!type->isPointerTy())
+ return false;
+ auto ptr_type = type->getPointerElementType();
- return ptr_type->isStructTy() && ptr_type->getStructName().startswith("struct.rs_allocation");
+ return ptr_type->isStructTy() &&
+ ptr_type->getStructName().startswith("struct.rs_allocation");
}
-bool
-isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst)
-{
- (void)module;
- if (!call_inst->hasByValArgument())
- return false;
- for (const auto ¶m : call_inst->operand_values())
- if (isRSAllocationPtrTy(param->getType()))
- return true;
+bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
+ (void)module;
+ if (!call_inst->hasByValArgument())
return false;
+ for (const auto ¶m : call_inst->operand_values())
+ if (isRSAllocationPtrTy(param->getType()))
+ return true;
+ return false;
}
-llvm::FunctionType *
-cloneToStructRetFnTy(llvm::CallInst *call_inst)
-{
- // on x86 StructReturn functions return a pointer to the return value, rather than the return
- // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf section 6).
- // We create a return type by getting the pointer type of the old return type, and inserting a new
- // initial argument of pointer type of the original return type.
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
-
- assert(call_inst && "no CallInst");
- llvm::Function *orig = call_inst->getCalledFunction();
- assert(orig && "CallInst has no called function");
- llvm::FunctionType *orig_type = orig->getFunctionType();
- auto name = orig->getName();
- if (log)
- log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__, name.str().c_str());
-
- unsigned num_params = orig_type->getNumParams();
- std::vector<llvm::Type *> new_params{num_params + 1, nullptr};
- std::vector<llvm::Type *> params{orig_type->param_begin(), orig_type->param_end()};
-
- // This may not work if the function is somehow declared void as llvm is strongly typed
- // and represents void* with i8*
- assert(!orig_type->getReturnType()->isVoidTy() && "Cannot add StructRet attribute to void function");
- llvm::PointerType *return_type_ptr_type = llvm::PointerType::getUnqual(orig->getReturnType());
- assert(return_type_ptr_type && "failed to get function return type PointerType");
- if (!return_type_ptr_type)
- return nullptr;
-
- if (log)
- log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n", __FUNCTION__,
- (void *)return_type_ptr_type);
- // put the the sret pointer argument in place at the beginning of the argument list.
- params.emplace(params.begin(), return_type_ptr_type);
- assert(params.size() == num_params + 1);
- return llvm::FunctionType::get(return_type_ptr_type, params, orig->isVarArg());
+llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
+ // on x86 StructReturn functions return a pointer to the return value, rather
+ // than the return
+ // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf
+ // section 6).
+ // We create a return type by getting the pointer type of the old return type,
+ // and inserting a new
+ // initial argument of pointer type of the original return type.
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
+
+ assert(call_inst && "no CallInst");
+ llvm::Function *orig = call_inst->getCalledFunction();
+ assert(orig && "CallInst has no called function");
+ llvm::FunctionType *orig_type = orig->getFunctionType();
+ auto name = orig->getName();
+ if (log)
+ log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__,
+ name.str().c_str());
+
+ unsigned num_params = orig_type->getNumParams();
+ std::vector<llvm::Type *> new_params{num_params + 1, nullptr};
+ std::vector<llvm::Type *> params{orig_type->param_begin(),
+ orig_type->param_end()};
+
+ // This may not work if the function is somehow declared void as llvm is
+ // strongly typed
+ // and represents void* with i8*
+ assert(!orig_type->getReturnType()->isVoidTy() &&
+ "Cannot add StructRet attribute to void function");
+ llvm::PointerType *return_type_ptr_type =
+ llvm::PointerType::getUnqual(orig->getReturnType());
+ assert(return_type_ptr_type &&
+ "failed to get function return type PointerType");
+ if (!return_type_ptr_type)
+ return nullptr;
+
+ if (log)
+ log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n",
+ __FUNCTION__, (void *)return_type_ptr_type);
+ // put the the sret pointer argument in place at the beginning of the argument
+ // list.
+ params.emplace(params.begin(), return_type_ptr_type);
+ assert(params.size() == num_params + 1);
+ return llvm::FunctionType::get(return_type_ptr_type, params,
+ orig->isVarArg());
}
-bool
-findRSCallSites(llvm::Module &module, std::set<llvm::CallInst *> &rs_callsites,
- bool (*predicate)(llvm::Module &, llvm::CallInst *))
-{
- bool found = false;
-
- for (auto &func : module.getFunctionList())
- for (auto &block : func.getBasicBlockList())
- for (auto &inst : block)
- {
- llvm::CallInst *call_inst = llvm::dyn_cast_or_null<llvm::CallInst>(&inst);
- if (!call_inst || !call_inst->getCalledFunction())
- // This is not the call-site you are looking for...
- continue;
- if (isRSAPICall(module, call_inst) && predicate(module, call_inst))
- {
- rs_callsites.insert(call_inst);
- found = true;
- }
- }
- return found;
+bool findRSCallSites(llvm::Module &module,
+ std::set<llvm::CallInst *> &rs_callsites,
+ bool (*predicate)(llvm::Module &, llvm::CallInst *)) {
+ bool found = false;
+
+ for (auto &func : module.getFunctionList())
+ for (auto &block : func.getBasicBlockList())
+ for (auto &inst : block) {
+ llvm::CallInst *call_inst =
+ llvm::dyn_cast_or_null<llvm::CallInst>(&inst);
+ if (!call_inst || !call_inst->getCalledFunction())
+ // This is not the call-site you are looking for...
+ continue;
+ if (isRSAPICall(module, call_inst) && predicate(module, call_inst)) {
+ rs_callsites.insert(call_inst);
+ found = true;
+ }
+ }
+ return found;
}
-bool
-fixupX86StructRetCalls(llvm::Module &module)
-{
- bool changed = false;
- // changing a basic block while iterating over it seems to have some undefined behaviour
- // going on so we find all RS callsites first, then fix them up after consuming
- // the iterator.
- std::set<llvm::CallInst *> rs_callsites;
- if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
- return false;
-
- for (auto call_inst : rs_callsites)
- {
- llvm::FunctionType *new_func_type = cloneToStructRetFnTy(call_inst);
- assert(new_func_type && "failed to clone functionType for Renderscript ABI fixup");
-
- llvm::CallSite call_site(call_inst);
- llvm::Function *func = call_inst->getCalledFunction();
- assert(func && "cannot resolve function in RenderScriptRuntime");
- // Copy the original call arguments
- std::vector<llvm::Value *> new_call_args(call_site.arg_begin(), call_site.arg_end());
-
- // Allocate enough space to store the return value of the original function
- // we pass a pointer to this allocation as the StructRet param, and then copy its
- // value into the lldb return value
- llvm::AllocaInst *return_value_alloc =
- new llvm::AllocaInst(func->getReturnType(), "var_vector_return_alloc", call_inst);
- // use the new allocation as the new first argument
- new_call_args.emplace(new_call_args.begin(), llvm::cast<llvm::Value>(return_value_alloc));
- llvm::PointerType *new_func_ptr_type = llvm::PointerType::get(new_func_type, 0);
- // Create the type cast from the old function type to the new one
- llvm::Constant *new_func_cast =
- llvm::ConstantExpr::getCast(llvm::Instruction::BitCast, func, new_func_ptr_type);
- // create an allocation for a new function pointer
- llvm::AllocaInst *new_func_ptr = new llvm::AllocaInst(new_func_ptr_type, "new_func_ptr", call_inst);
- // store the new_func_cast to the newly allocated space
- (void)new llvm::StoreInst(new_func_cast, new_func_ptr, "new_func_ptr_load_cast", call_inst);
- // load the new function address ready for a jump
- llvm::LoadInst *new_func_addr_load = new llvm::LoadInst(new_func_ptr, "load_func_pointer", call_inst);
- // and create a callinstruction from it
- llvm::CallInst *new_call_inst =
- llvm::CallInst::Create(new_func_addr_load, new_call_args, "new_func_call", call_inst);
- new_call_inst->setCallingConv(call_inst->getCallingConv());
- new_call_inst->setTailCall(call_inst->isTailCall());
- llvm::LoadInst *lldb_save_result_address = new llvm::LoadInst(return_value_alloc, "save_return_val", call_inst);
-
- // Now remove the old broken call
- call_inst->replaceAllUsesWith(lldb_save_result_address);
- call_inst->eraseFromParent();
- changed = true;
- }
- return changed;
+bool fixupX86StructRetCalls(llvm::Module &module) {
+ bool changed = false;
+ // changing a basic block while iterating over it seems to have some undefined
+ // behaviour
+ // going on so we find all RS callsites first, then fix them up after
+ // consuming
+ // the iterator.
+ std::set<llvm::CallInst *> rs_callsites;
+ if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
+ return false;
+
+ for (auto call_inst : rs_callsites) {
+ llvm::FunctionType *new_func_type = cloneToStructRetFnTy(call_inst);
+ assert(new_func_type &&
+ "failed to clone functionType for Renderscript ABI fixup");
+
+ llvm::CallSite call_site(call_inst);
+ llvm::Function *func = call_inst->getCalledFunction();
+ assert(func && "cannot resolve function in RenderScriptRuntime");
+ // Copy the original call arguments
+ std::vector<llvm::Value *> new_call_args(call_site.arg_begin(),
+ call_site.arg_end());
+
+ // Allocate enough space to store the return value of the original function
+ // we pass a pointer to this allocation as the StructRet param, and then
+ // copy its
+ // value into the lldb return value
+ llvm::AllocaInst *return_value_alloc = new llvm::AllocaInst(
+ func->getReturnType(), "var_vector_return_alloc", call_inst);
+ // use the new allocation as the new first argument
+ new_call_args.emplace(new_call_args.begin(),
+ llvm::cast<llvm::Value>(return_value_alloc));
+ llvm::PointerType *new_func_ptr_type =
+ llvm::PointerType::get(new_func_type, 0);
+ // Create the type cast from the old function type to the new one
+ llvm::Constant *new_func_cast = llvm::ConstantExpr::getCast(
+ llvm::Instruction::BitCast, func, new_func_ptr_type);
+ // create an allocation for a new function pointer
+ llvm::AllocaInst *new_func_ptr =
+ new llvm::AllocaInst(new_func_ptr_type, "new_func_ptr", call_inst);
+ // store the new_func_cast to the newly allocated space
+ (void)new llvm::StoreInst(new_func_cast, new_func_ptr,
+ "new_func_ptr_load_cast", call_inst);
+ // load the new function address ready for a jump
+ llvm::LoadInst *new_func_addr_load =
+ new llvm::LoadInst(new_func_ptr, "load_func_pointer", call_inst);
+ // and create a callinstruction from it
+ llvm::CallInst *new_call_inst = llvm::CallInst::Create(
+ new_func_addr_load, new_call_args, "new_func_call", call_inst);
+ new_call_inst->setCallingConv(call_inst->getCallingConv());
+ new_call_inst->setTailCall(call_inst->isTailCall());
+ llvm::LoadInst *lldb_save_result_address =
+ new llvm::LoadInst(return_value_alloc, "save_return_val", call_inst);
+
+ // Now remove the old broken call
+ call_inst->replaceAllUsesWith(lldb_save_result_address);
+ call_inst->eraseFromParent();
+ changed = true;
+ }
+ return changed;
}
-bool
-fixupRSAllocationStructByValCalls(llvm::Module &module)
-{
- // On x86_64, calls to functions in the RS runtime that take an `rs_allocation` type argument
- // are actually handled as by-ref params by bcc, but appear to be passed by value by lldb (the callsite all use
- // `struct byval`).
- // On x86_64 Linux, struct arguments are transferred in registers if the struct size is no bigger than
- // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf) section 7.1 "Passing and returning objects"
- // otherwise passed on the stack.
- // an object of type `rs_allocation` is actually 256bits, so should be passed on the stack. However, code generated
- // by bcc actually treats formal params of type `rs_allocation` as `rs_allocation *` so we need to convert the
- // calling convention to pass by reference, and remove any hint of byval from formal parameters.
- bool changed = false;
- std::set<llvm::CallInst *> rs_callsites;
- if (!findRSCallSites(module, rs_callsites, isRSAllocationTyCallSite))
- return false;
-
- std::set<llvm::Function *> rs_functions;
-
- // for all call instructions
- for (auto call_inst : rs_callsites)
- {
- // add the called function to a set so that we can strip its byval attributes in another pass
- rs_functions.insert(call_inst->getCalledFunction());
-
- // get the function attributes
- llvm::AttributeSet call_attribs = call_inst->getAttributes();
-
- // iterate over the argument attributes
- for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i)
- {
- // if this argument is passed by val
- if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal))
- {
- // strip away the byval attribute
- call_inst->removeAttribute(i, llvm::Attribute::get(module.getContext(), llvm::Attribute::ByVal));
- changed = true;
- }
- }
+bool fixupRSAllocationStructByValCalls(llvm::Module &module) {
+ // On x86_64, calls to functions in the RS runtime that take an
+ // `rs_allocation` type argument
+ // are actually handled as by-ref params by bcc, but appear to be passed by
+ // value by lldb (the callsite all use
+ // `struct byval`).
+ // On x86_64 Linux, struct arguments are transferred in registers if the
+ // struct size is no bigger than
+ // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf)
+ // section 7.1 "Passing and returning objects"
+ // otherwise passed on the stack.
+ // an object of type `rs_allocation` is actually 256bits, so should be passed
+ // on the stack. However, code generated
+ // by bcc actually treats formal params of type `rs_allocation` as
+ // `rs_allocation *` so we need to convert the
+ // calling convention to pass by reference, and remove any hint of byval from
+ // formal parameters.
+ bool changed = false;
+ std::set<llvm::CallInst *> rs_callsites;
+ if (!findRSCallSites(module, rs_callsites, isRSAllocationTyCallSite))
+ return false;
+
+ std::set<llvm::Function *> rs_functions;
+
+ // for all call instructions
+ for (auto call_inst : rs_callsites) {
+ // add the called function to a set so that we can strip its byval
+ // attributes in another pass
+ rs_functions.insert(call_inst->getCalledFunction());
+
+ // get the function attributes
+ llvm::AttributeSet call_attribs = call_inst->getAttributes();
+
+ // iterate over the argument attributes
+ for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i) {
+ // if this argument is passed by val
+ if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal)) {
+ // strip away the byval attribute
+ call_inst->removeAttribute(
+ i,
+ llvm::Attribute::get(module.getContext(), llvm::Attribute::ByVal));
+ changed = true;
+ }
}
+ }
- llvm::AttributeSet attr_byval = llvm::AttributeSet::get(module.getContext(), 1u, llvm::Attribute::ByVal);
+ llvm::AttributeSet attr_byval =
+ llvm::AttributeSet::get(module.getContext(), 1u, llvm::Attribute::ByVal);
- // for all called function decls
- for (auto func : rs_functions)
- {
- // inspect all of the arguments in the call
- llvm::SymbolTableList<llvm::Argument> &argList = func->getArgumentList();
- for (auto &arg : argList)
- {
- if (arg.hasByValAttr())
- {
- arg.removeAttr(attr_byval);
- changed = true;
- }
- }
+ // for all called function decls
+ for (auto func : rs_functions) {
+ // inspect all of the arguments in the call
+ llvm::SymbolTableList<llvm::Argument> &argList = func->getArgumentList();
+ for (auto &arg : argList) {
+ if (arg.hasByValAttr()) {
+ arg.removeAttr(attr_byval);
+ changed = true;
+ }
}
- return changed;
+ }
+ return changed;
}
} // end anonymous namespace
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
-
-bool
-fixupX86FunctionCalls(llvm::Module &module)
-{
- return fixupX86StructRetCalls(module);
+namespace lldb_private {
+namespace lldb_renderscript {
+
+bool fixupX86FunctionCalls(llvm::Module &module) {
+ return fixupX86StructRetCalls(module);
}
-bool
-fixupX86_64FunctionCalls(llvm::Module &module)
-{
- bool changed = false;
- changed |= fixupX86StructRetCalls(module);
- changed |= fixupRSAllocationStructByValCalls(module);
- return changed;
+bool fixupX86_64FunctionCalls(llvm::Module &module) {
+ bool changed = false;
+ changed |= fixupX86StructRetCalls(module);
+ changed |= fixupRSAllocationStructByValCalls(module);
+ return changed;
}
} // end namespace lldb_renderscript
Modified: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h (original)
+++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h Tue Sep 6 15:57:50 2016
@@ -12,16 +12,12 @@
#include "llvm/IR/Module.h"
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
+namespace lldb_private {
+namespace lldb_renderscript {
-bool
-fixupX86FunctionCalls(llvm::Module &module);
+bool fixupX86FunctionCalls(llvm::Module &module);
-bool
-fixupX86_64FunctionCalls(llvm::Module &module);
+bool fixupX86_64FunctionCalls(llvm::Module &module);
}
}
#endif
Modified: lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp (original)
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp Tue Sep 6 15:57:50 2016
@@ -11,80 +11,66 @@
#include "lldb/Target/MemoryHistory.h"
-#include "lldb/lldb-private.h"
+#include "Plugins/Process/Utility/HistoryThread.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/UserExpression.h"
-#include "lldb/Target/ThreadList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Core/Module.h"
-#include "Plugins/Process/Utility/HistoryThread.h"
-#include "lldb/Core/ValueObject.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/lldb-private.h"
#include <sstream>
using namespace lldb;
using namespace lldb_private;
-MemoryHistorySP
-MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
-{
- if (!process_sp.get())
- return NULL;
-
- Target & target = process_sp->GetTarget();
-
- const ModuleList &target_modules = target.GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- const size_t num_modules = target_modules.GetSize();
- for (size_t i = 0; i < num_modules; ++i)
- {
- Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
+MemoryHistorySP MemoryHistoryASan::CreateInstance(const ProcessSP &process_sp) {
+ if (!process_sp.get())
+ return NULL;
- const Symbol* symbol = module_pointer->FindFirstSymbolWithNameAndType(
- ConstString("__asan_get_alloc_stack"),
- lldb::eSymbolTypeAny);
+ Target &target = process_sp->GetTarget();
- if (symbol != nullptr)
- return MemoryHistorySP(new MemoryHistoryASan(process_sp));
- }
+ const ModuleList &target_modules = target.GetImages();
+ std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
+ const size_t num_modules = target_modules.GetSize();
+ for (size_t i = 0; i < num_modules; ++i) {
+ Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
- return MemoryHistorySP();
-}
+ const Symbol *symbol = module_pointer->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny);
+
+ if (symbol != nullptr)
+ return MemoryHistorySP(new MemoryHistoryASan(process_sp));
+ }
-void
-MemoryHistoryASan::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "ASan memory history provider.",
- CreateInstance);
+ return MemoryHistorySP();
}
-void
-MemoryHistoryASan::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void MemoryHistoryASan::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), "ASan memory history provider.", CreateInstance);
}
+void MemoryHistoryASan::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
-ConstString
-MemoryHistoryASan::GetPluginNameStatic()
-{
- static ConstString g_name("asan");
- return g_name;
+ConstString MemoryHistoryASan::GetPluginNameStatic() {
+ static ConstString g_name("asan");
+ return g_name;
}
-MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
-{
- if (process_sp)
- m_process_wp = process_sp;
+MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp) {
+ if (process_sp)
+ m_process_wp = process_sp;
}
-const char *
-memory_history_asan_command_prefix = R"(
+const char *memory_history_asan_command_prefix = R"(
extern "C"
{
size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, int *thread_id);
@@ -102,109 +88,117 @@ memory_history_asan_command_prefix = R"(
};
)";
-const char *
-memory_history_asan_command_format = R"(
+const char *memory_history_asan_command_format =
+ R"(
data t;
- t.alloc_count = __asan_get_alloc_stack((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid);
- t.free_count = __asan_get_free_stack((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid);
+ t.alloc_count = __asan_get_alloc_stack((void *)0x%)" PRIx64
+ R"(, t.alloc_trace, 256, &t.alloc_tid);
+ t.free_count = __asan_get_free_stack((void *)0x%)" PRIx64
+ R"(, t.free_trace, 256, &t.free_tid);
t;
)";
-static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObjectSP return_value_sp, const char *type, const char *thread_name, HistoryThreads & result)
-{
- std::string count_path = "." + std::string(type) + "_count";
- std::string tid_path = "." + std::string(type) + "_tid";
- std::string trace_path = "." + std::string(type) + "_trace";
-
- ValueObjectSP count_sp = return_value_sp->GetValueForExpressionPath(count_path.c_str());
- ValueObjectSP tid_sp = return_value_sp->GetValueForExpressionPath(tid_path.c_str());
-
- if (!count_sp || !tid_sp)
- return;
-
- int count = count_sp->GetValueAsUnsigned(0);
- tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1;
-
- if (count <= 0)
- return;
-
- ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str());
-
- if (!trace_sp)
- return;
+static void CreateHistoryThreadFromValueObject(ProcessSP process_sp,
+ ValueObjectSP return_value_sp,
+ const char *type,
+ const char *thread_name,
+ HistoryThreads &result) {
+ std::string count_path = "." + std::string(type) + "_count";
+ std::string tid_path = "." + std::string(type) + "_tid";
+ std::string trace_path = "." + std::string(type) + "_trace";
+
+ ValueObjectSP count_sp =
+ return_value_sp->GetValueForExpressionPath(count_path.c_str());
+ ValueObjectSP tid_sp =
+ return_value_sp->GetValueForExpressionPath(tid_path.c_str());
+
+ if (!count_sp || !tid_sp)
+ return;
+
+ int count = count_sp->GetValueAsUnsigned(0);
+ tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1;
+
+ if (count <= 0)
+ return;
+
+ ValueObjectSP trace_sp =
+ return_value_sp->GetValueForExpressionPath(trace_path.c_str());
+
+ if (!trace_sp)
+ return;
+
+ std::vector<lldb::addr_t> pcs;
+ for (int i = 0; i < count; i++) {
+ addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);
+ if (pc == 0 || pc == 1 || pc == LLDB_INVALID_ADDRESS)
+ continue;
+ pcs.push_back(pc);
+ }
+
+ HistoryThread *history_thread =
+ new HistoryThread(*process_sp, tid, pcs, 0, false);
+ ThreadSP new_thread_sp(history_thread);
+ std::ostringstream thread_name_with_number;
+ thread_name_with_number << thread_name << " Thread " << tid;
+ history_thread->SetThreadName(thread_name_with_number.str().c_str());
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains
+ // the object
+ process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
+ result.push_back(new_thread_sp);
+}
- std::vector<lldb::addr_t> pcs;
- for (int i = 0; i < count; i++)
- {
- addr_t pc = trace_sp->GetChildAtIndex(i, true)->GetValueAsUnsigned(0);
- if (pc == 0 || pc == 1 || pc == LLDB_INVALID_ADDRESS)
- continue;
- pcs.push_back(pc);
- }
-
- HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, 0, false);
- ThreadSP new_thread_sp(history_thread);
- std::ostringstream thread_name_with_number;
- thread_name_with_number << thread_name << " Thread " << tid;
- history_thread->SetThreadName(thread_name_with_number.str().c_str());
- // Save this in the Process' ExtendedThreadList so a strong pointer retains the object
- process_sp->GetExtendedThreadList().AddThread (new_thread_sp);
- result.push_back(new_thread_sp);
-}
-
-#define GET_STACK_FUNCTION_TIMEOUT_USEC 2*1000*1000
-
-HistoryThreads
-MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
-{
- HistoryThreads result;
-
- ProcessSP process_sp = m_process_wp.lock();
- if (! process_sp)
- return result;
-
- ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread();
- if (!thread_sp)
- return result;
-
- StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
- if (!frame_sp)
- return result;
-
- ExecutionContext exe_ctx (frame_sp);
- ValueObjectSP return_value_sp;
- StreamString expr;
- Error eval_error;
- expr.Printf(memory_history_asan_command_format, address, address);
-
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(true);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
- options.SetPrefix(memory_history_asan_command_prefix);
- options.SetAutoApplyFixIts(false);
- options.SetLanguage(eLanguageTypeObjC_plus_plus);
-
- ExpressionResults expr_result = UserExpression::Evaluate (exe_ctx,
- options,
- expr.GetData(),
- "",
- return_value_sp,
- eval_error);
- if (expr_result != eExpressionCompleted) {
- process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString());
- return result;
- }
+#define GET_STACK_FUNCTION_TIMEOUT_USEC 2 * 1000 * 1000
- if (!return_value_sp)
- return result;
-
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated by", result);
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated by", result);
-
+HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
+ HistoryThreads result;
+
+ ProcessSP process_sp = m_process_wp.lock();
+ if (!process_sp)
+ return result;
+
+ ThreadSP thread_sp =
+ process_sp->GetThreadList().GetExpressionExecutionThread();
+ if (!thread_sp)
return result;
+
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ if (!frame_sp)
+ return result;
+
+ ExecutionContext exe_ctx(frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ Error eval_error;
+ expr.Printf(memory_history_asan_command_format, address, address);
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
+ options.SetPrefix(memory_history_asan_command_prefix);
+ options.SetAutoApplyFixIts(false);
+ options.SetLanguage(eLanguageTypeObjC_plus_plus);
+
+ ExpressionResults expr_result = UserExpression::Evaluate(
+ exe_ctx, options, expr.GetData(), "", return_value_sp, eval_error);
+ if (expr_result != eExpressionCompleted) {
+ process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf(
+ "Warning: Cannot evaluate AddressSanitizer expression:\n%s\n",
+ eval_error.AsCString());
+ return result;
+ }
+
+ if (!return_value_sp)
+ return result;
+
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free",
+ "Memory deallocated by", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc",
+ "Memory allocated by", result);
+
+ return result;
}
Modified: lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h (original)
+++ lldb/trunk/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h Tue Sep 6 15:57:50 2016
@@ -14,51 +14,40 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/Process.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-class MemoryHistoryASan : public lldb_private::MemoryHistory
-{
+class MemoryHistoryASan : public lldb_private::MemoryHistory {
public:
- ~MemoryHistoryASan() override = default;
+ ~MemoryHistoryASan() override = default;
+
+ static lldb::MemoryHistorySP
+ CreateInstance(const lldb::ProcessSP &process_sp);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ lldb_private::ConstString GetPluginName() override {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ lldb_private::HistoryThreads GetHistoryThreads(lldb::addr_t address) override;
- static lldb::MemoryHistorySP
- CreateInstance (const lldb::ProcessSP &process_sp);
-
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- lldb_private::ConstString
- GetPluginName() override
- {
- return GetPluginNameStatic();
- }
-
- uint32_t
- GetPluginVersion() override
- {
- return 1;
- }
-
- lldb_private::HistoryThreads
- GetHistoryThreads(lldb::addr_t address) override;
-
private:
- MemoryHistoryASan(const lldb::ProcessSP &process_sp);
-
- lldb::ProcessWP m_process_wp;
+ MemoryHistoryASan(const lldb::ProcessSP &process_sp);
+
+ lldb::ProcessWP m_process_wp;
};
} // namespace lldb_private
-
+
#endif // liblldb_MemoryHistoryASan_h_
Modified: lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp Tue Sep 6 15:57:50 2016
@@ -11,18 +11,17 @@
#if defined(_WIN32) || defined(__ANDROID_NDK__)
// Defines from ar, missing on Windows
-#define ARMAG "!<arch>\n"
-#define SARMAG 8
-#define ARFMAG "`\n"
-
-typedef struct ar_hdr
-{
- char ar_name[16];
- char ar_date[12];
- char ar_uid[6], ar_gid[6];
- char ar_mode[8];
- char ar_size[10];
- char ar_fmag[2];
+#define ARMAG "!<arch>\n"
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+typedef struct ar_hdr {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6], ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+ char ar_fmag[2];
} ar_hdr;
#else
#include <ar.h>
@@ -40,591 +39,473 @@ typedef struct ar_hdr
using namespace lldb;
using namespace lldb_private;
-
-
-ObjectContainerBSDArchive::Object::Object() :
- ar_name(),
- ar_date(0),
- ar_uid(0),
- ar_gid(0),
- ar_mode(0),
- ar_size(0),
- ar_file_offset(0),
- ar_file_size(0)
-{
-}
-
-void
-ObjectContainerBSDArchive::Object::Clear()
-{
- ar_name.Clear();
- ar_date = 0;
- ar_uid = 0;
- ar_gid = 0;
- ar_mode = 0;
- ar_size = 0;
- ar_file_offset = 0;
- ar_file_size = 0;
+ObjectContainerBSDArchive::Object::Object()
+ : ar_name(), ar_date(0), ar_uid(0), ar_gid(0), ar_mode(0), ar_size(0),
+ ar_file_offset(0), ar_file_size(0) {}
+
+void ObjectContainerBSDArchive::Object::Clear() {
+ ar_name.Clear();
+ ar_date = 0;
+ ar_uid = 0;
+ ar_gid = 0;
+ ar_mode = 0;
+ ar_size = 0;
+ ar_file_offset = 0;
+ ar_file_size = 0;
}
lldb::offset_t
-ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::offset_t offset)
-{
- size_t ar_name_len = 0;
- std::string str;
- char *err;
-
-
- // File header
- //
- // The common format is as follows.
- //
- // Offset Length Name Format
- // 0 16 File name ASCII right padded with spaces (no spaces allowed in file name)
- // 16 12 File mod Decimal as cstring right padded with spaces
- // 28 6 Owner ID Decimal as cstring right padded with spaces
- // 34 6 Group ID Decimal as cstring right padded with spaces
- // 40 8 File mode Octal as cstring right padded with spaces
- // 48 10 File byte size Decimal as cstring right padded with spaces
- // 58 2 File magic 0x60 0x0A
-
- // Make sure there is enough data for the file header and bail if not
- if (!data.ValidOffsetForDataOfSize(offset, 60))
- return LLDB_INVALID_OFFSET;
-
- str.assign ((const char *)data.GetData(&offset, 16), 16);
- if (str.find("#1/") == 0)
- {
- // If the name is longer than 16 bytes, or contains an embedded space
- // then it will use this format where the length of the name is
- // here and the name characters are after this header.
- ar_name_len = strtoul(str.c_str() + 3, &err, 10);
- }
- else
- {
- // Strip off any trailing spaces.
- const size_t last_pos = str.find_last_not_of(' ');
- if (last_pos != std::string::npos)
- {
- if (last_pos + 1 < 16)
- str.erase (last_pos + 1);
- }
- ar_name.SetCString(str.c_str());
- }
+ObjectContainerBSDArchive::Object::Extract(const DataExtractor &data,
+ lldb::offset_t offset) {
+ size_t ar_name_len = 0;
+ std::string str;
+ char *err;
+
+ // File header
+ //
+ // The common format is as follows.
+ //
+ // Offset Length Name Format
+ // 0 16 File name ASCII right padded with spaces (no spaces
+ // allowed in file name)
+ // 16 12 File mod Decimal as cstring right padded with
+ // spaces
+ // 28 6 Owner ID Decimal as cstring right padded with
+ // spaces
+ // 34 6 Group ID Decimal as cstring right padded with
+ // spaces
+ // 40 8 File mode Octal as cstring right padded with
+ // spaces
+ // 48 10 File byte size Decimal as cstring right padded with
+ // spaces
+ // 58 2 File magic 0x60 0x0A
- str.assign ((const char *)data.GetData(&offset, 12), 12);
- ar_date = strtoul(str.c_str(), &err, 10);
-
- str.assign ((const char *)data.GetData(&offset, 6), 6);
- ar_uid = strtoul(str.c_str(), &err, 10);
-
- str.assign ((const char *)data.GetData(&offset, 6), 6);
- ar_gid = strtoul(str.c_str(), &err, 10);
-
- str.assign ((const char *)data.GetData(&offset, 8), 8);
- ar_mode = strtoul(str.c_str(), &err, 8);
-
- str.assign ((const char *)data.GetData(&offset, 10), 10);
- ar_size = strtoul(str.c_str(), &err, 10);
-
- str.assign ((const char *)data.GetData(&offset, 2), 2);
- if (str == ARFMAG)
- {
- if (ar_name_len > 0)
- {
- const void *ar_name_ptr = data.GetData(&offset, ar_name_len);
- // Make sure there was enough data for the string value and bail if not
- if (ar_name_ptr == NULL)
- return LLDB_INVALID_OFFSET;
- str.assign ((const char *)ar_name_ptr, ar_name_len);
- ar_name.SetCString (str.c_str());
- }
- ar_file_offset = offset;
- ar_file_size = ar_size - ar_name_len;
- return offset;
- }
+ // Make sure there is enough data for the file header and bail if not
+ if (!data.ValidOffsetForDataOfSize(offset, 60))
return LLDB_INVALID_OFFSET;
-}
-
-ObjectContainerBSDArchive::Archive::Archive
-(
- const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &time,
- lldb::offset_t file_offset,
- lldb_private::DataExtractor &data
-) :
- m_arch (arch),
- m_time (time),
- m_file_offset (file_offset),
- m_objects(),
- m_data (data)
-{
-}
-
-ObjectContainerBSDArchive::Archive::~Archive ()
-{
-}
-
-size_t
-ObjectContainerBSDArchive::Archive::ParseObjects ()
-{
- DataExtractor &data = m_data;
- std::string str;
- lldb::offset_t offset = 0;
- str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
- if (str == ARMAG)
- {
- Object obj;
- do
- {
- offset = obj.Extract (data, offset);
- if (offset == LLDB_INVALID_OFFSET)
- break;
- size_t obj_idx = m_objects.size();
- m_objects.push_back(obj);
- // Insert all of the C strings out of order for now...
- m_object_name_to_index_map.Append (obj.ar_name.GetCString(), obj_idx);
- offset += obj.ar_file_size;
- obj.Clear();
- } while (data.ValidOffset(offset));
- // Now sort all of the object name pointers
- m_object_name_to_index_map.Sort ();
+ str.assign((const char *)data.GetData(&offset, 16), 16);
+ if (str.find("#1/") == 0) {
+ // If the name is longer than 16 bytes, or contains an embedded space
+ // then it will use this format where the length of the name is
+ // here and the name characters are after this header.
+ ar_name_len = strtoul(str.c_str() + 3, &err, 10);
+ } else {
+ // Strip off any trailing spaces.
+ const size_t last_pos = str.find_last_not_of(' ');
+ if (last_pos != std::string::npos) {
+ if (last_pos + 1 < 16)
+ str.erase(last_pos + 1);
+ }
+ ar_name.SetCString(str.c_str());
+ }
+
+ str.assign((const char *)data.GetData(&offset, 12), 12);
+ ar_date = strtoul(str.c_str(), &err, 10);
+
+ str.assign((const char *)data.GetData(&offset, 6), 6);
+ ar_uid = strtoul(str.c_str(), &err, 10);
+
+ str.assign((const char *)data.GetData(&offset, 6), 6);
+ ar_gid = strtoul(str.c_str(), &err, 10);
+
+ str.assign((const char *)data.GetData(&offset, 8), 8);
+ ar_mode = strtoul(str.c_str(), &err, 8);
+
+ str.assign((const char *)data.GetData(&offset, 10), 10);
+ ar_size = strtoul(str.c_str(), &err, 10);
+
+ str.assign((const char *)data.GetData(&offset, 2), 2);
+ if (str == ARFMAG) {
+ if (ar_name_len > 0) {
+ const void *ar_name_ptr = data.GetData(&offset, ar_name_len);
+ // Make sure there was enough data for the string value and bail if not
+ if (ar_name_ptr == NULL)
+ return LLDB_INVALID_OFFSET;
+ str.assign((const char *)ar_name_ptr, ar_name_len);
+ ar_name.SetCString(str.c_str());
}
- return m_objects.size();
+ ar_file_offset = offset;
+ ar_file_size = ar_size - ar_name_len;
+ return offset;
+ }
+ return LLDB_INVALID_OFFSET;
+}
+
+ObjectContainerBSDArchive::Archive::Archive(const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &time,
+ lldb::offset_t file_offset,
+ lldb_private::DataExtractor &data)
+ : m_arch(arch), m_time(time), m_file_offset(file_offset), m_objects(),
+ m_data(data) {}
+
+ObjectContainerBSDArchive::Archive::~Archive() {}
+
+size_t ObjectContainerBSDArchive::Archive::ParseObjects() {
+ DataExtractor &data = m_data;
+ std::string str;
+ lldb::offset_t offset = 0;
+ str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
+ if (str == ARMAG) {
+ Object obj;
+ do {
+ offset = obj.Extract(data, offset);
+ if (offset == LLDB_INVALID_OFFSET)
+ break;
+ size_t obj_idx = m_objects.size();
+ m_objects.push_back(obj);
+ // Insert all of the C strings out of order for now...
+ m_object_name_to_index_map.Append(obj.ar_name.GetCString(), obj_idx);
+ offset += obj.ar_file_size;
+ obj.Clear();
+ } while (data.ValidOffset(offset));
+
+ // Now sort all of the object name pointers
+ m_object_name_to_index_map.Sort();
+ }
+ return m_objects.size();
}
ObjectContainerBSDArchive::Object *
-ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name, const TimeValue &object_mod_time)
-{
- const ObjectNameToIndexMap::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
- if (match)
- {
- if (object_mod_time.IsValid())
- {
- const uint64_t object_date = object_mod_time.GetAsSecondsSinceJan1_1970();
- if (m_objects[match->value].ar_date == object_date)
- return &m_objects[match->value];
- const ObjectNameToIndexMap::Entry *next_match = m_object_name_to_index_map.FindNextValueForName (match);
- while (next_match)
- {
- if (m_objects[next_match->value].ar_date == object_date)
- return &m_objects[next_match->value];
- next_match = m_object_name_to_index_map.FindNextValueForName (next_match);
- }
- }
- else
- {
- return &m_objects[match->value];
- }
+ObjectContainerBSDArchive::Archive::FindObject(
+ const ConstString &object_name, const TimeValue &object_mod_time) {
+ const ObjectNameToIndexMap::Entry *match =
+ m_object_name_to_index_map.FindFirstValueForName(
+ object_name.GetCString());
+ if (match) {
+ if (object_mod_time.IsValid()) {
+ const uint64_t object_date = object_mod_time.GetAsSecondsSinceJan1_1970();
+ if (m_objects[match->value].ar_date == object_date)
+ return &m_objects[match->value];
+ const ObjectNameToIndexMap::Entry *next_match =
+ m_object_name_to_index_map.FindNextValueForName(match);
+ while (next_match) {
+ if (m_objects[next_match->value].ar_date == object_date)
+ return &m_objects[next_match->value];
+ next_match =
+ m_object_name_to_index_map.FindNextValueForName(next_match);
+ }
+ } else {
+ return &m_objects[match->value];
}
- return NULL;
+ }
+ return NULL;
}
-
ObjectContainerBSDArchive::Archive::shared_ptr
-ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, const ArchSpec &arch, const TimeValue &time, lldb::offset_t file_offset)
-{
- std::lock_guard<std::recursive_mutex> guard(Archive::GetArchiveCacheMutex());
- shared_ptr archive_sp;
- Archive::Map &archive_map = Archive::GetArchiveCache ();
- Archive::Map::iterator pos = archive_map.find (file);
- // Don't cache a value for "archive_map.end()" below since we might
- // delete an archive entry...
- while (pos != archive_map.end() && pos->first == file)
- {
- bool match = true;
- if (arch.IsValid() && pos->second->GetArchitecture().IsCompatibleMatch(arch) == false)
- match = false;
- else if (file_offset != LLDB_INVALID_OFFSET && pos->second->GetFileOffset() != file_offset)
- match = false;
- if (match)
- {
- if (pos->second->GetModificationTime() == time)
- {
- return pos->second;
- }
- else
- {
- // We have a file at the same path with the same architecture
- // whose modification time doesn't match. It doesn't make sense
- // for us to continue to use this BSD archive since we cache only
- // the object info which consists of file time info and also the
- // file offset and file size of any contained objects. Since
- // this information is now out of date, we won't get the correct
- // information if we go and extract the file data, so we should
- // remove the old and outdated entry.
- archive_map.erase (pos);
- pos = archive_map.find (file);
- continue; // Continue to next iteration so we don't increment pos below...
- }
- }
- ++pos;
- }
- return archive_sp;
+ObjectContainerBSDArchive::Archive::FindCachedArchive(
+ const FileSpec &file, const ArchSpec &arch, const TimeValue &time,
+ lldb::offset_t file_offset) {
+ std::lock_guard<std::recursive_mutex> guard(Archive::GetArchiveCacheMutex());
+ shared_ptr archive_sp;
+ Archive::Map &archive_map = Archive::GetArchiveCache();
+ Archive::Map::iterator pos = archive_map.find(file);
+ // Don't cache a value for "archive_map.end()" below since we might
+ // delete an archive entry...
+ while (pos != archive_map.end() && pos->first == file) {
+ bool match = true;
+ if (arch.IsValid() &&
+ pos->second->GetArchitecture().IsCompatibleMatch(arch) == false)
+ match = false;
+ else if (file_offset != LLDB_INVALID_OFFSET &&
+ pos->second->GetFileOffset() != file_offset)
+ match = false;
+ if (match) {
+ if (pos->second->GetModificationTime() == time) {
+ return pos->second;
+ } else {
+ // We have a file at the same path with the same architecture
+ // whose modification time doesn't match. It doesn't make sense
+ // for us to continue to use this BSD archive since we cache only
+ // the object info which consists of file time info and also the
+ // file offset and file size of any contained objects. Since
+ // this information is now out of date, we won't get the correct
+ // information if we go and extract the file data, so we should
+ // remove the old and outdated entry.
+ archive_map.erase(pos);
+ pos = archive_map.find(file);
+ continue; // Continue to next iteration so we don't increment pos
+ // below...
+ }
+ }
+ ++pos;
+ }
+ return archive_sp;
}
ObjectContainerBSDArchive::Archive::shared_ptr
-ObjectContainerBSDArchive::Archive::ParseAndCacheArchiveForFile
-(
- const FileSpec &file,
- const ArchSpec &arch,
- const TimeValue &time,
- lldb::offset_t file_offset,
- DataExtractor &data
-)
-{
- shared_ptr archive_sp(new Archive (arch, time, file_offset, data));
- if (archive_sp)
- {
- const size_t num_objects = archive_sp->ParseObjects ();
- if (num_objects > 0)
- {
- std::lock_guard<std::recursive_mutex> guard(Archive::GetArchiveCacheMutex());
- Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
- }
- else
- {
- archive_sp.reset();
- }
+ObjectContainerBSDArchive::Archive::ParseAndCacheArchiveForFile(
+ const FileSpec &file, const ArchSpec &arch, const TimeValue &time,
+ lldb::offset_t file_offset, DataExtractor &data) {
+ shared_ptr archive_sp(new Archive(arch, time, file_offset, data));
+ if (archive_sp) {
+ const size_t num_objects = archive_sp->ParseObjects();
+ if (num_objects > 0) {
+ std::lock_guard<std::recursive_mutex> guard(
+ Archive::GetArchiveCacheMutex());
+ Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
+ } else {
+ archive_sp.reset();
}
- return archive_sp;
+ }
+ return archive_sp;
}
ObjectContainerBSDArchive::Archive::Map &
-ObjectContainerBSDArchive::Archive::GetArchiveCache ()
-{
- static Archive::Map g_archive_map;
- return g_archive_map;
+ObjectContainerBSDArchive::Archive::GetArchiveCache() {
+ static Archive::Map g_archive_map;
+ return g_archive_map;
}
std::recursive_mutex &
-ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex()
-{
- static std::recursive_mutex g_archive_map_mutex;
- return g_archive_map_mutex;
-}
-
-void
-ObjectContainerBSDArchive::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- GetModuleSpecifications);
-}
-
-void
-ObjectContainerBSDArchive::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
-}
-
-
-lldb_private::ConstString
-ObjectContainerBSDArchive::GetPluginNameStatic()
-{
- static ConstString g_name("bsd-archive");
- return g_name;
-}
-
-const char *
-ObjectContainerBSDArchive::GetPluginDescriptionStatic()
-{
- return "BSD Archive object container reader.";
-}
-
-
-ObjectContainer *
-ObjectContainerBSDArchive::CreateInstance
-(
- const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const FileSpec *file,
- lldb::offset_t file_offset,
- lldb::offset_t length)
-{
- ConstString object_name (module_sp->GetObjectName());
- if (object_name)
- {
- if (data_sp)
- {
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
- DataExtractor data;
- data.SetData (data_sp, data_offset, length);
- if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
- {
- Timer scoped_timer (LLVM_PRETTY_FUNCTION,
- "ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
- module_sp->GetFileSpec().GetPath().c_str(),
- static_cast<const void*>(file),
- static_cast<uint64_t>(file_offset),
- static_cast<uint64_t>(length));
-
- // Map the entire .a file to be sure that we don't lose any data if the file
- // gets updated by a new build while this .a file is being used for debugging
- DataBufferSP archive_data_sp (file->MemoryMapFileContentsIfLocal(file_offset, length));
- lldb::offset_t archive_data_offset = 0;
-
- Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
- module_sp->GetArchitecture(),
- module_sp->GetModificationTime(),
- file_offset));
- std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp,
- archive_data_sp,
- archive_data_offset,
- file,
- file_offset,
- length));
-
- if (container_ap.get())
- {
- if (archive_sp)
- {
- // We already have this archive in our cache, use it
- container_ap->SetArchive (archive_sp);
- return container_ap.release();
- }
- else if (container_ap->ParseHeader())
- return container_ap.release();
- }
- }
- }
- else
- {
- // No data, just check for a cached archive
- Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
- module_sp->GetArchitecture(),
- module_sp->GetModificationTime(),
- file_offset));
- if (archive_sp)
- {
- std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, data_offset, file, file_offset, length));
-
- if (container_ap.get())
- {
- // We already have this archive in our cache, use it
- container_ap->SetArchive (archive_sp);
- return container_ap.release();
- }
- }
- }
- }
- return NULL;
-}
-
-
-
-bool
-ObjectContainerBSDArchive::MagicBytesMatch (const DataExtractor &data)
-{
- uint32_t offset = 0;
- const char* armag = (const char* )data.PeekData (offset, sizeof(ar_hdr));
- if (armag && ::strncmp(armag, ARMAG, SARMAG) == 0)
- {
- armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG;
- if (strncmp(armag, ARFMAG, 2) == 0)
- return true;
- }
- return false;
-}
-
-ObjectContainerBSDArchive::ObjectContainerBSDArchive
-(
- const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t file_offset,
- lldb::offset_t size
-) :
- ObjectContainer (module_sp, file, file_offset, size, data_sp, data_offset),
- m_archive_sp ()
-{
-}
-void
-ObjectContainerBSDArchive::SetArchive (Archive::shared_ptr &archive_sp)
-{
- m_archive_sp = archive_sp;
-}
-
-
-
-ObjectContainerBSDArchive::~ObjectContainerBSDArchive()
-{
-}
-
-bool
-ObjectContainerBSDArchive::ParseHeader ()
-{
- if (m_archive_sp.get() == NULL)
- {
- if (m_data.GetByteSize() > 0)
- {
- ModuleSP module_sp (GetModule());
- if (module_sp)
- {
- m_archive_sp = Archive::ParseAndCacheArchiveForFile (m_file,
- module_sp->GetArchitecture(),
- module_sp->GetModificationTime(),
- m_offset,
- m_data);
- }
- // Clear the m_data that contains the entire archive
- // data and let our m_archive_sp hold onto the data.
- m_data.Clear();
- }
- }
- return m_archive_sp.get() != NULL;
-}
-
-void
-ObjectContainerBSDArchive::Dump (Stream *s) const
-{
- s->Printf("%p: ", static_cast<const void*>(this));
+ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex() {
+ static std::recursive_mutex g_archive_map_mutex;
+ return g_archive_map_mutex;
+}
+
+void ObjectContainerBSDArchive::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ GetModuleSpecifications);
+}
+
+void ObjectContainerBSDArchive::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString ObjectContainerBSDArchive::GetPluginNameStatic() {
+ static ConstString g_name("bsd-archive");
+ return g_name;
+}
+
+const char *ObjectContainerBSDArchive::GetPluginDescriptionStatic() {
+ return "BSD Archive object container reader.";
+}
+
+ObjectContainer *ObjectContainerBSDArchive::CreateInstance(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length) {
+ ConstString object_name(module_sp->GetObjectName());
+ if (object_name) {
+ if (data_sp) {
+ // We have data, which means this is the first 512 bytes of the file
+ // Check to see if the magic bytes match and if they do, read the entire
+ // table of contents for the archive and cache it
+ DataExtractor data;
+ data.SetData(data_sp, data_offset, length);
+ if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) {
+ Timer scoped_timer(
+ LLVM_PRETTY_FUNCTION,
+ "ObjectContainerBSDArchive::CreateInstance (module = %s, file = "
+ "%p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
+ module_sp->GetFileSpec().GetPath().c_str(),
+ static_cast<const void *>(file), static_cast<uint64_t>(file_offset),
+ static_cast<uint64_t>(length));
+
+ // Map the entire .a file to be sure that we don't lose any data if the
+ // file
+ // gets updated by a new build while this .a file is being used for
+ // debugging
+ DataBufferSP archive_data_sp(
+ file->MemoryMapFileContentsIfLocal(file_offset, length));
+ lldb::offset_t archive_data_offset = 0;
+
+ Archive::shared_ptr archive_sp(Archive::FindCachedArchive(
+ *file, module_sp->GetArchitecture(),
+ module_sp->GetModificationTime(), file_offset));
+ std::unique_ptr<ObjectContainerBSDArchive> container_ap(
+ new ObjectContainerBSDArchive(module_sp, archive_data_sp,
+ archive_data_offset, file,
+ file_offset, length));
+
+ if (container_ap.get()) {
+ if (archive_sp) {
+ // We already have this archive in our cache, use it
+ container_ap->SetArchive(archive_sp);
+ return container_ap.release();
+ } else if (container_ap->ParseHeader())
+ return container_ap.release();
+ }
+ }
+ } else {
+ // No data, just check for a cached archive
+ Archive::shared_ptr archive_sp(Archive::FindCachedArchive(
+ *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(),
+ file_offset));
+ if (archive_sp) {
+ std::unique_ptr<ObjectContainerBSDArchive> container_ap(
+ new ObjectContainerBSDArchive(module_sp, data_sp, data_offset, file,
+ file_offset, length));
+
+ if (container_ap.get()) {
+ // We already have this archive in our cache, use it
+ container_ap->SetArchive(archive_sp);
+ return container_ap.release();
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+bool ObjectContainerBSDArchive::MagicBytesMatch(const DataExtractor &data) {
+ uint32_t offset = 0;
+ const char *armag = (const char *)data.PeekData(offset, sizeof(ar_hdr));
+ if (armag && ::strncmp(armag, ARMAG, SARMAG) == 0) {
+ armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG;
+ if (strncmp(armag, ARFMAG, 2) == 0)
+ return true;
+ }
+ return false;
+}
+
+ObjectContainerBSDArchive::ObjectContainerBSDArchive(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t size)
+ : ObjectContainer(module_sp, file, file_offset, size, data_sp, data_offset),
+ m_archive_sp() {}
+void ObjectContainerBSDArchive::SetArchive(Archive::shared_ptr &archive_sp) {
+ m_archive_sp = archive_sp;
+}
+
+ObjectContainerBSDArchive::~ObjectContainerBSDArchive() {}
+
+bool ObjectContainerBSDArchive::ParseHeader() {
+ if (m_archive_sp.get() == NULL) {
+ if (m_data.GetByteSize() > 0) {
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ m_archive_sp = Archive::ParseAndCacheArchiveForFile(
+ m_file, module_sp->GetArchitecture(),
+ module_sp->GetModificationTime(), m_offset, m_data);
+ }
+ // Clear the m_data that contains the entire archive
+ // data and let our m_archive_sp hold onto the data.
+ m_data.Clear();
+ }
+ }
+ return m_archive_sp.get() != NULL;
+}
+
+void ObjectContainerBSDArchive::Dump(Stream *s) const {
+ s->Printf("%p: ", static_cast<const void *>(this));
+ s->Indent();
+ const size_t num_archs = GetNumArchitectures();
+ const size_t num_objects = GetNumObjects();
+ s->Printf("ObjectContainerBSDArchive, num_archs = %" PRIu64
+ ", num_objects = %" PRIu64 "",
+ (uint64_t)num_archs, (uint64_t)num_objects);
+ uint32_t i;
+ ArchSpec arch;
+ s->IndentMore();
+ for (i = 0; i < num_archs; i++) {
s->Indent();
- const size_t num_archs = GetNumArchitectures();
- const size_t num_objects = GetNumObjects();
- s->Printf("ObjectContainerBSDArchive, num_archs = %" PRIu64 ", num_objects = %" PRIu64 "", (uint64_t)num_archs, (uint64_t)num_objects);
- uint32_t i;
- ArchSpec arch;
- s->IndentMore();
- for (i=0; i<num_archs; i++)
- {
- s->Indent();
- GetArchitectureAtIndex(i, arch);
- s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
- }
- for (i=0; i<num_objects; i++)
- {
- s->Indent();
- s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
- }
- s->IndentLess();
- s->EOL();
-}
-
-ObjectFileSP
-ObjectContainerBSDArchive::GetObjectFile (const FileSpec *file)
-{
- ModuleSP module_sp (GetModule());
- if (module_sp)
- {
- if (module_sp->GetObjectName() && m_archive_sp)
- {
- Object *object = m_archive_sp->FindObject (module_sp->GetObjectName(),
- module_sp->GetObjectModificationTime());
- if (object)
- {
- lldb::offset_t data_offset = object->ar_file_offset;
- return ObjectFile::FindPlugin (module_sp,
- file,
- m_offset + object->ar_file_offset,
- object->ar_file_size,
- m_archive_sp->GetData().GetSharedDataBuffer(),
- data_offset);
- }
- }
+ GetArchitectureAtIndex(i, arch);
+ s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
+ }
+ for (i = 0; i < num_objects; i++) {
+ s->Indent();
+ s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex(i));
+ }
+ s->IndentLess();
+ s->EOL();
+}
+
+ObjectFileSP ObjectContainerBSDArchive::GetObjectFile(const FileSpec *file) {
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ if (module_sp->GetObjectName() && m_archive_sp) {
+ Object *object = m_archive_sp->FindObject(
+ module_sp->GetObjectName(), module_sp->GetObjectModificationTime());
+ if (object) {
+ lldb::offset_t data_offset = object->ar_file_offset;
+ return ObjectFile::FindPlugin(
+ module_sp, file, m_offset + object->ar_file_offset,
+ object->ar_file_size, m_archive_sp->GetData().GetSharedDataBuffer(),
+ data_offset);
+ }
}
- return ObjectFileSP();
+ }
+ return ObjectFileSP();
}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-ObjectContainerBSDArchive::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ObjectContainerBSDArchive::GetPluginVersion()
-{
- return 1;
+lldb_private::ConstString ObjectContainerBSDArchive::GetPluginName() {
+ return GetPluginNameStatic();
}
+uint32_t ObjectContainerBSDArchive::GetPluginVersion() { return 1; }
-size_t
-ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t file_size,
- lldb_private::ModuleSpecList &specs)
-{
-
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
- DataExtractor data;
- data.SetData (data_sp, data_offset, data_sp->GetByteSize());
- if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
- {
- const size_t initial_count = specs.GetSize();
- TimeValue file_mod_time = file.GetModificationTime();
- Archive::shared_ptr archive_sp (Archive::FindCachedArchive (file, ArchSpec(), file_mod_time, file_offset));
- bool set_archive_arch = false;
- if (!archive_sp)
- {
- set_archive_arch = true;
- DataBufferSP data_sp (file.MemoryMapFileContentsIfLocal(file_offset, file_size));
- data.SetData (data_sp, 0, data_sp->GetByteSize());
- archive_sp = Archive::ParseAndCacheArchiveForFile(file, ArchSpec(), file_mod_time, file_offset, data);
- }
-
- if (archive_sp)
- {
- const size_t num_objects = archive_sp->GetNumObjects();
- for (size_t idx = 0; idx < num_objects; ++idx)
- {
- const Object *object = archive_sp->GetObjectAtIndex (idx);
- if (object)
- {
- const lldb::offset_t object_file_offset = file_offset + object->ar_file_offset;
- if (object->ar_file_offset < file_size && file_size > object_file_offset)
- {
- if (ObjectFile::GetModuleSpecifications(file,
- object_file_offset,
- file_size - object_file_offset,
- specs))
- {
- ModuleSpec &spec = specs.GetModuleSpecRefAtIndex (specs.GetSize() - 1);
- TimeValue object_mod_time;
- object_mod_time.OffsetWithSeconds(object->ar_date);
- spec.GetObjectName () = object->ar_name;
- spec.SetObjectOffset (object_file_offset);
- spec.SetObjectSize (file_size - object_file_offset);
- spec.GetObjectModificationTime () = object_mod_time;
- }
- }
- }
- }
- }
- const size_t end_count = specs.GetSize();
- size_t num_specs_added = end_count - initial_count;
- if (set_archive_arch && num_specs_added > 0)
- {
- // The archive was created but we didn't have an architecture
- // so we need to set it
- for (size_t i=initial_count; i<end_count; ++ i)
- {
- ModuleSpec module_spec;
- if (specs.GetModuleSpecAtIndex(i, module_spec))
- {
- if (module_spec.GetArchitecture().IsValid())
- {
- archive_sp->SetArchitecture (module_spec.GetArchitecture());
- break;
- }
- }
+size_t ObjectContainerBSDArchive::GetModuleSpecifications(
+ const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, lldb::offset_t file_offset,
+ lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) {
+
+ // We have data, which means this is the first 512 bytes of the file
+ // Check to see if the magic bytes match and if they do, read the entire
+ // table of contents for the archive and cache it
+ DataExtractor data;
+ data.SetData(data_sp, data_offset, data_sp->GetByteSize());
+ if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) {
+ const size_t initial_count = specs.GetSize();
+ TimeValue file_mod_time = file.GetModificationTime();
+ Archive::shared_ptr archive_sp(Archive::FindCachedArchive(
+ file, ArchSpec(), file_mod_time, file_offset));
+ bool set_archive_arch = false;
+ if (!archive_sp) {
+ set_archive_arch = true;
+ DataBufferSP data_sp(
+ file.MemoryMapFileContentsIfLocal(file_offset, file_size));
+ data.SetData(data_sp, 0, data_sp->GetByteSize());
+ archive_sp = Archive::ParseAndCacheArchiveForFile(
+ file, ArchSpec(), file_mod_time, file_offset, data);
+ }
+
+ if (archive_sp) {
+ const size_t num_objects = archive_sp->GetNumObjects();
+ for (size_t idx = 0; idx < num_objects; ++idx) {
+ const Object *object = archive_sp->GetObjectAtIndex(idx);
+ if (object) {
+ const lldb::offset_t object_file_offset =
+ file_offset + object->ar_file_offset;
+ if (object->ar_file_offset < file_size &&
+ file_size > object_file_offset) {
+ if (ObjectFile::GetModuleSpecifications(
+ file, object_file_offset, file_size - object_file_offset,
+ specs)) {
+ ModuleSpec &spec =
+ specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1);
+ TimeValue object_mod_time;
+ object_mod_time.OffsetWithSeconds(object->ar_date);
+ spec.GetObjectName() = object->ar_name;
+ spec.SetObjectOffset(object_file_offset);
+ spec.SetObjectSize(file_size - object_file_offset);
+ spec.GetObjectModificationTime() = object_mod_time;
}
+ }
}
- return num_specs_added;
+ }
}
- return 0;
+ const size_t end_count = specs.GetSize();
+ size_t num_specs_added = end_count - initial_count;
+ if (set_archive_arch && num_specs_added > 0) {
+ // The archive was created but we didn't have an architecture
+ // so we need to set it
+ for (size_t i = initial_count; i < end_count; ++i) {
+ ModuleSpec module_spec;
+ if (specs.GetModuleSpecAtIndex(i, module_spec)) {
+ if (module_spec.GetArchitecture().IsValid()) {
+ archive_sp->SetArchitecture(module_spec.GetArchitecture());
+ break;
+ }
+ }
+ }
+ }
+ return num_specs_added;
+ }
+ return 0;
}
Modified: lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h (original)
+++ lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h Tue Sep 6 15:57:50 2016
@@ -16,217 +16,161 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Symbol/ObjectContainer.h"
-class ObjectContainerBSDArchive :
- public lldb_private::ObjectContainer
-{
+class ObjectContainerBSDArchive : public lldb_private::ObjectContainer {
public:
- ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- ~ObjectContainerBSDArchive() override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::ObjectContainer *
- CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- static size_t
- GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs);
-
- static bool
- MagicBytesMatch (const lldb_private::DataExtractor &data);
-
- //------------------------------------------------------------------
- // Member Functions
- //------------------------------------------------------------------
- bool
- ParseHeader() override;
-
- size_t
- GetNumObjects() const override
- {
- if (m_archive_sp)
- return m_archive_sp->GetNumObjects();
- return 0;
- }
+ ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ ~ObjectContainerBSDArchive() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectContainer *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ static bool MagicBytesMatch(const lldb_private::DataExtractor &data);
+
+ //------------------------------------------------------------------
+ // Member Functions
+ //------------------------------------------------------------------
+ bool ParseHeader() override;
- void
- Dump(lldb_private::Stream *s) const override;
+ size_t GetNumObjects() const override {
+ if (m_archive_sp)
+ return m_archive_sp->GetNumObjects();
+ return 0;
+ }
- lldb::ObjectFileSP
- GetObjectFile(const lldb_private::FileSpec *file) override;
+ void Dump(lldb_private::Stream *s) const override;
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override;
- uint32_t
- GetPluginVersion() override;
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
protected:
- struct Object
- {
- Object();
-
- void
- Clear();
-
- lldb::offset_t
- Extract (const lldb_private::DataExtractor& data, lldb::offset_t offset);
-
- lldb_private::ConstString ar_name; // name
- uint32_t ar_date; // modification time
- uint16_t ar_uid; // user id
- uint16_t ar_gid; // group id
- uint16_t ar_mode; // octal file permissions
- uint32_t ar_size; // size in bytes
- lldb::offset_t ar_file_offset; // file offset in bytes from the beginning of the file of the object data
- lldb::offset_t ar_file_size; // length of the object data
-
- typedef std::vector<Object> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
- };
-
- class Archive
- {
- public:
- typedef std::shared_ptr<Archive> shared_ptr;
- typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
-
- Archive(const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time,
- lldb::offset_t file_offset,
- lldb_private::DataExtractor &data);
-
- ~Archive();
-
- static Map &
- GetArchiveCache ();
-
- static std::recursive_mutex &
- GetArchiveCacheMutex();
-
- static Archive::shared_ptr
- FindCachedArchive (const lldb_private::FileSpec &file,
- const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time,
- lldb::offset_t file_offset);
-
- static Archive::shared_ptr
- ParseAndCacheArchiveForFile (const lldb_private::FileSpec &file,
- const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time,
- lldb::offset_t file_offset,
- lldb_private::DataExtractor &data);
-
- size_t
- GetNumObjects () const
- {
- return m_objects.size();
- }
-
- const Object *
- GetObjectAtIndex (size_t idx)
- {
- if (idx < m_objects.size())
- return &m_objects[idx];
- return NULL;
- }
-
- size_t
- ParseObjects ();
-
- Object *
- FindObject (const lldb_private::ConstString &object_name,
- const lldb_private::TimeValue &object_mod_time);
-
- lldb::offset_t
- GetFileOffset () const
- {
- return m_file_offset;
- }
-
- const lldb_private::TimeValue &
- GetModificationTime()
- {
- return m_time;
- }
-
- const lldb_private::ArchSpec &
- GetArchitecture () const
- {
- return m_arch;
- }
-
- void
- SetArchitecture (const lldb_private::ArchSpec &arch)
- {
- m_arch = arch;
- }
-
- bool
- HasNoExternalReferences() const;
-
- lldb_private::DataExtractor &
- GetData ()
- {
- return m_data;
- }
-
- protected:
- typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap;
- //----------------------------------------------------------------------
- // Member Variables
- //----------------------------------------------------------------------
- lldb_private::ArchSpec m_arch;
- lldb_private::TimeValue m_time;
- lldb::offset_t m_file_offset;
- Object::collection m_objects;
- ObjectNameToIndexMap m_object_name_to_index_map;
- lldb_private::DataExtractor m_data; ///< The data for this object container so we don't lose data if the .a files gets modified
- };
+ struct Object {
+ Object();
+
+ void Clear();
+
+ lldb::offset_t Extract(const lldb_private::DataExtractor &data,
+ lldb::offset_t offset);
+
+ lldb_private::ConstString ar_name; // name
+ uint32_t ar_date; // modification time
+ uint16_t ar_uid; // user id
+ uint16_t ar_gid; // group id
+ uint16_t ar_mode; // octal file permissions
+ uint32_t ar_size; // size in bytes
+ lldb::offset_t ar_file_offset; // file offset in bytes from the beginning of
+ // the file of the object data
+ lldb::offset_t ar_file_size; // length of the object data
+
+ typedef std::vector<Object> collection;
+ typedef collection::iterator iterator;
+ typedef collection::const_iterator const_iterator;
+ };
+
+ class Archive {
+ public:
+ typedef std::shared_ptr<Archive> shared_ptr;
+ typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
+
+ Archive(const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &mod_time, lldb::offset_t file_offset,
+ lldb_private::DataExtractor &data);
+
+ ~Archive();
+
+ static Map &GetArchiveCache();
+
+ static std::recursive_mutex &GetArchiveCacheMutex();
+
+ static Archive::shared_ptr FindCachedArchive(
+ const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &mod_time, lldb::offset_t file_offset);
+
+ static Archive::shared_ptr ParseAndCacheArchiveForFile(
+ const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &mod_time, lldb::offset_t file_offset,
+ lldb_private::DataExtractor &data);
+
+ size_t GetNumObjects() const { return m_objects.size(); }
+
+ const Object *GetObjectAtIndex(size_t idx) {
+ if (idx < m_objects.size())
+ return &m_objects[idx];
+ return NULL;
+ }
+
+ size_t ParseObjects();
+
+ Object *FindObject(const lldb_private::ConstString &object_name,
+ const lldb_private::TimeValue &object_mod_time);
+
+ lldb::offset_t GetFileOffset() const { return m_file_offset; }
+
+ const lldb_private::TimeValue &GetModificationTime() { return m_time; }
+
+ const lldb_private::ArchSpec &GetArchitecture() const { return m_arch; }
+
+ void SetArchitecture(const lldb_private::ArchSpec &arch) { m_arch = arch; }
+
+ bool HasNoExternalReferences() const;
+
+ lldb_private::DataExtractor &GetData() { return m_data; }
+
+ protected:
+ typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap;
+ //----------------------------------------------------------------------
+ // Member Variables
+ //----------------------------------------------------------------------
+ lldb_private::ArchSpec m_arch;
+ lldb_private::TimeValue m_time;
+ lldb::offset_t m_file_offset;
+ Object::collection m_objects;
+ ObjectNameToIndexMap m_object_name_to_index_map;
+ lldb_private::DataExtractor m_data; ///< The data for this object container
+ ///so we don't lose data if the .a files
+ ///gets modified
+ };
- void
- SetArchive (Archive::shared_ptr &archive_sp);
+ void SetArchive(Archive::shared_ptr &archive_sp);
- Archive::shared_ptr m_archive_sp;
+ Archive::shared_ptr m_archive_sp;
};
#endif // liblldb_ObjectContainerBSDArchive_h_
Modified: lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp Tue Sep 6 15:57:50 2016
@@ -21,290 +21,219 @@ using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
-void
-ObjectContainerUniversalMachO::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- GetModuleSpecifications);
-}
-
-void
-ObjectContainerUniversalMachO::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void ObjectContainerUniversalMachO::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ GetModuleSpecifications);
}
-
-lldb_private::ConstString
-ObjectContainerUniversalMachO::GetPluginNameStatic()
-{
- static ConstString g_name("mach-o");
- return g_name;
-}
-
-const char *
-ObjectContainerUniversalMachO::GetPluginDescriptionStatic()
-{
- return "Universal mach-o object container reader.";
+void ObjectContainerUniversalMachO::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-
-ObjectContainer *
-ObjectContainerUniversalMachO::CreateInstance
-(
- const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const FileSpec *file,
- lldb::offset_t file_offset,
- lldb::offset_t length
-)
-{
- // We get data when we aren't trying to look for cached container information,
- // so only try and look for an architecture slice if we get data
- if (data_sp)
- {
- DataExtractor data;
- data.SetData (data_sp, data_offset, length);
- if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
- {
- std::unique_ptr<ObjectContainerUniversalMachO> container_ap(new ObjectContainerUniversalMachO (module_sp, data_sp, data_offset, file, file_offset, length));
- if (container_ap->ParseHeader())
- {
- return container_ap.release();
- }
- }
- }
- return NULL;
+lldb_private::ConstString ObjectContainerUniversalMachO::GetPluginNameStatic() {
+ static ConstString g_name("mach-o");
+ return g_name;
}
-bool
-ObjectContainerUniversalMachO::MagicBytesMatch (const DataExtractor &data)
-{
- lldb::offset_t offset = 0;
- uint32_t magic = data.GetU32(&offset);
- return magic == FAT_MAGIC || magic == FAT_CIGAM;
-}
-
-ObjectContainerUniversalMachO::ObjectContainerUniversalMachO
-(
- const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const FileSpec *file,
- lldb::offset_t file_offset,
- lldb::offset_t length
-) :
- ObjectContainer (module_sp, file, file_offset, length, data_sp, data_offset),
- m_header(),
- m_fat_archs()
-{
- memset(&m_header, 0, sizeof(m_header));
-}
-
-
-ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO()
-{
-}
-
-bool
-ObjectContainerUniversalMachO::ParseHeader ()
-{
- bool success = ParseHeader (m_data, m_header, m_fat_archs);
- // We no longer need any data, we parsed all we needed to parse
- // and cached it in m_header and m_fat_archs
- m_data.Clear();
- return success;
-}
-
-bool
-ObjectContainerUniversalMachO::ParseHeader (lldb_private::DataExtractor &data,
- llvm::MachO::fat_header &header,
- std::vector<llvm::MachO::fat_arch> &fat_archs)
-{
- bool success = false;
- // Store the file offset for this universal file as we could have a universal .o file
- // in a BSD archive, or be contained in another kind of object.
- // Universal mach-o files always have their headers in big endian.
- lldb::offset_t offset = 0;
- data.SetByteOrder (eByteOrderBig);
- header.magic = data.GetU32(&offset);
- fat_archs.clear();
-
- if (header.magic == FAT_MAGIC)
- {
-
- data.SetAddressByteSize(4);
-
- header.nfat_arch = data.GetU32(&offset);
-
- // Now we should have enough data for all of the fat headers, so lets index
- // them so we know how many architectures that this universal binary contains.
- uint32_t arch_idx = 0;
- for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx)
- {
- if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch)))
- {
- fat_arch arch;
- if (data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t)))
- fat_archs.push_back(arch);
- }
- }
- success = true;
- }
- else
- {
- memset(&header, 0, sizeof(header));
- }
- return success;
+const char *ObjectContainerUniversalMachO::GetPluginDescriptionStatic() {
+ return "Universal mach-o object container reader.";
}
-void
-ObjectContainerUniversalMachO::Dump (Stream *s) const
-{
- s->Printf("%p: ", static_cast<const void*>(this));
+ObjectContainer *ObjectContainerUniversalMachO::CreateInstance(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length) {
+ // We get data when we aren't trying to look for cached container information,
+ // so only try and look for an architecture slice if we get data
+ if (data_sp) {
+ DataExtractor data;
+ data.SetData(data_sp, data_offset, length);
+ if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) {
+ std::unique_ptr<ObjectContainerUniversalMachO> container_ap(
+ new ObjectContainerUniversalMachO(module_sp, data_sp, data_offset,
+ file, file_offset, length));
+ if (container_ap->ParseHeader()) {
+ return container_ap.release();
+ }
+ }
+ }
+ return NULL;
+}
+
+bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) {
+ lldb::offset_t offset = 0;
+ uint32_t magic = data.GetU32(&offset);
+ return magic == FAT_MAGIC || magic == FAT_CIGAM;
+}
+
+ObjectContainerUniversalMachO::ObjectContainerUniversalMachO(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length)
+ : ObjectContainer(module_sp, file, file_offset, length, data_sp,
+ data_offset),
+ m_header(), m_fat_archs() {
+ memset(&m_header, 0, sizeof(m_header));
+}
+
+ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() {}
+
+bool ObjectContainerUniversalMachO::ParseHeader() {
+ bool success = ParseHeader(m_data, m_header, m_fat_archs);
+ // We no longer need any data, we parsed all we needed to parse
+ // and cached it in m_header and m_fat_archs
+ m_data.Clear();
+ return success;
+}
+
+bool ObjectContainerUniversalMachO::ParseHeader(
+ lldb_private::DataExtractor &data, llvm::MachO::fat_header &header,
+ std::vector<llvm::MachO::fat_arch> &fat_archs) {
+ bool success = false;
+ // Store the file offset for this universal file as we could have a universal
+ // .o file
+ // in a BSD archive, or be contained in another kind of object.
+ // Universal mach-o files always have their headers in big endian.
+ lldb::offset_t offset = 0;
+ data.SetByteOrder(eByteOrderBig);
+ header.magic = data.GetU32(&offset);
+ fat_archs.clear();
+
+ if (header.magic == FAT_MAGIC) {
+
+ data.SetAddressByteSize(4);
+
+ header.nfat_arch = data.GetU32(&offset);
+
+ // Now we should have enough data for all of the fat headers, so lets index
+ // them so we know how many architectures that this universal binary
+ // contains.
+ uint32_t arch_idx = 0;
+ for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) {
+ if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) {
+ fat_arch arch;
+ if (data.GetU32(&offset, &arch, sizeof(fat_arch) / sizeof(uint32_t)))
+ fat_archs.push_back(arch);
+ }
+ }
+ success = true;
+ } else {
+ memset(&header, 0, sizeof(header));
+ }
+ return success;
+}
+
+void ObjectContainerUniversalMachO::Dump(Stream *s) const {
+ s->Printf("%p: ", static_cast<const void *>(this));
+ s->Indent();
+ const size_t num_archs = GetNumArchitectures();
+ const size_t num_objects = GetNumObjects();
+ s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu",
+ num_archs, num_objects);
+ uint32_t i;
+ ArchSpec arch;
+ s->IndentMore();
+ for (i = 0; i < num_archs; i++) {
s->Indent();
- const size_t num_archs = GetNumArchitectures();
- const size_t num_objects = GetNumObjects();
- s->Printf("ObjectContainerUniversalMachO, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
- uint32_t i;
- ArchSpec arch;
- s->IndentMore();
- for (i=0; i<num_archs; i++)
- {
- s->Indent();
- GetArchitectureAtIndex(i, arch);
- s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
- }
- for (i=0; i<num_objects; i++)
- {
- s->Indent();
- s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
- }
- s->IndentLess();
- s->EOL();
-}
-
-size_t
-ObjectContainerUniversalMachO::GetNumArchitectures () const
-{
- return m_header.nfat_arch;
-}
-
-bool
-ObjectContainerUniversalMachO::GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const
-{
- if (idx < m_header.nfat_arch)
- {
- arch.SetArchitecture (eArchTypeMachO, m_fat_archs[idx].cputype, m_fat_archs[idx].cpusubtype);
- return true;
- }
- return false;
+ GetArchitectureAtIndex(i, arch);
+ s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
+ }
+ for (i = 0; i < num_objects; i++) {
+ s->Indent();
+ s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex(i));
+ }
+ s->IndentLess();
+ s->EOL();
+}
+
+size_t ObjectContainerUniversalMachO::GetNumArchitectures() const {
+ return m_header.nfat_arch;
+}
+
+bool ObjectContainerUniversalMachO::GetArchitectureAtIndex(
+ uint32_t idx, ArchSpec &arch) const {
+ if (idx < m_header.nfat_arch) {
+ arch.SetArchitecture(eArchTypeMachO, m_fat_archs[idx].cputype,
+ m_fat_archs[idx].cpusubtype);
+ return true;
+ }
+ return false;
}
ObjectFileSP
-ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file)
-{
- uint32_t arch_idx = 0;
- ArchSpec arch;
- // If the module hasn't specified an architecture yet, set it to the default
- // architecture:
- ModuleSP module_sp (GetModule());
- if (module_sp)
- {
- if (!module_sp->GetArchitecture().IsValid())
- {
- arch = Target::GetDefaultArchitecture ();
- if (!arch.IsValid())
- arch.SetTriple (LLDB_ARCH_DEFAULT);
- }
- else
- arch = module_sp->GetArchitecture();
-
- ArchSpec curr_arch;
- // First, try to find an exact match for the Arch of the Target.
- for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
- {
- if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsExactMatch(curr_arch))
- break;
- }
-
- // Failing an exact match, try to find a compatible Arch of the Target.
- if (arch_idx >= m_header.nfat_arch)
- {
- for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx)
- {
- if (GetArchitectureAtIndex (arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch))
- break;
- }
- }
-
- if (arch_idx < m_header.nfat_arch)
- {
- DataBufferSP data_sp;
- lldb::offset_t data_offset = 0;
- return ObjectFile::FindPlugin (module_sp,
- file,
- m_offset + m_fat_archs[arch_idx].offset,
- m_fat_archs[arch_idx].size,
- data_sp,
- data_offset);
- }
+ObjectContainerUniversalMachO::GetObjectFile(const FileSpec *file) {
+ uint32_t arch_idx = 0;
+ ArchSpec arch;
+ // If the module hasn't specified an architecture yet, set it to the default
+ // architecture:
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ if (!module_sp->GetArchitecture().IsValid()) {
+ arch = Target::GetDefaultArchitecture();
+ if (!arch.IsValid())
+ arch.SetTriple(LLDB_ARCH_DEFAULT);
+ } else
+ arch = module_sp->GetArchitecture();
+
+ ArchSpec curr_arch;
+ // First, try to find an exact match for the Arch of the Target.
+ for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) {
+ if (GetArchitectureAtIndex(arch_idx, curr_arch) &&
+ arch.IsExactMatch(curr_arch))
+ break;
+ }
+
+ // Failing an exact match, try to find a compatible Arch of the Target.
+ if (arch_idx >= m_header.nfat_arch) {
+ for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) {
+ if (GetArchitectureAtIndex(arch_idx, curr_arch) &&
+ arch.IsCompatibleMatch(curr_arch))
+ break;
+ }
+ }
+
+ if (arch_idx < m_header.nfat_arch) {
+ DataBufferSP data_sp;
+ lldb::offset_t data_offset = 0;
+ return ObjectFile::FindPlugin(
+ module_sp, file, m_offset + m_fat_archs[arch_idx].offset,
+ m_fat_archs[arch_idx].size, data_sp, data_offset);
}
- return ObjectFileSP();
+ }
+ return ObjectFileSP();
}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-ObjectContainerUniversalMachO::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ObjectContainerUniversalMachO::GetPluginVersion()
-{
- return 1;
+lldb_private::ConstString ObjectContainerUniversalMachO::GetPluginName() {
+ return GetPluginNameStatic();
}
+uint32_t ObjectContainerUniversalMachO::GetPluginVersion() { return 1; }
-size_t
-ObjectContainerUniversalMachO::GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t file_size,
- lldb_private::ModuleSpecList &specs)
-{
- const size_t initial_count = specs.GetSize();
-
- DataExtractor data;
- data.SetData (data_sp, data_offset, data_sp->GetByteSize());
-
- if (ObjectContainerUniversalMachO::MagicBytesMatch(data))
- {
- llvm::MachO::fat_header header;
- std::vector<llvm::MachO::fat_arch> fat_archs;
- if (ParseHeader (data, header, fat_archs))
- {
- for (const llvm::MachO::fat_arch &fat_arch : fat_archs)
- {
- const lldb::offset_t slice_file_offset = fat_arch.offset + file_offset;
- if (fat_arch.offset < file_size && file_size > slice_file_offset)
- {
- ObjectFile::GetModuleSpecifications (file,
- slice_file_offset,
- file_size - slice_file_offset,
- specs);
- }
- }
+size_t ObjectContainerUniversalMachO::GetModuleSpecifications(
+ const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, lldb::offset_t file_offset,
+ lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) {
+ const size_t initial_count = specs.GetSize();
+
+ DataExtractor data;
+ data.SetData(data_sp, data_offset, data_sp->GetByteSize());
+
+ if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) {
+ llvm::MachO::fat_header header;
+ std::vector<llvm::MachO::fat_arch> fat_archs;
+ if (ParseHeader(data, header, fat_archs)) {
+ for (const llvm::MachO::fat_arch &fat_arch : fat_archs) {
+ const lldb::offset_t slice_file_offset = fat_arch.offset + file_offset;
+ if (fat_arch.offset < file_size && file_size > slice_file_offset) {
+ ObjectFile::GetModuleSpecifications(
+ file, slice_file_offset, file_size - slice_file_offset, specs);
}
+ }
}
- return specs.GetSize() - initial_count;
+ }
+ return specs.GetSize() - initial_count;
}
-
Modified: lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h (original)
+++ lldb/trunk/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h Tue Sep 6 15:57:50 2016
@@ -14,92 +14,73 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Utility/SafeMachO.h"
-class ObjectContainerUniversalMachO :
- public lldb_private::ObjectContainer
-{
+class ObjectContainerUniversalMachO : public lldb_private::ObjectContainer {
public:
- ObjectContainerUniversalMachO(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- ~ObjectContainerUniversalMachO() override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::ObjectContainer *
- CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- static size_t
- GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs);
-
- static bool
- MagicBytesMatch (const lldb_private::DataExtractor &data);
-
- //------------------------------------------------------------------
- // Member Functions
- //------------------------------------------------------------------
- bool
- ParseHeader() override;
-
- void
- Dump(lldb_private::Stream *s) const override;
-
- size_t
- GetNumArchitectures() const override;
-
- bool
- GetArchitectureAtIndex(uint32_t cpu_idx, lldb_private::ArchSpec& arch) const override;
-
- lldb::ObjectFileSP
- GetObjectFile(const lldb_private::FileSpec *file) override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ ObjectContainerUniversalMachO(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ ~ObjectContainerUniversalMachO() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectContainer *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
- uint32_t
- GetPluginVersion() override;
+ static bool MagicBytesMatch(const lldb_private::DataExtractor &data);
+
+ //------------------------------------------------------------------
+ // Member Functions
+ //------------------------------------------------------------------
+ bool ParseHeader() override;
+
+ void Dump(lldb_private::Stream *s) const override;
+
+ size_t GetNumArchitectures() const override;
+
+ bool GetArchitectureAtIndex(uint32_t cpu_idx,
+ lldb_private::ArchSpec &arch) const override;
+
+ lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
protected:
- llvm::MachO::fat_header m_header;
- std::vector<llvm::MachO::fat_arch> m_fat_archs;
-
- static bool
- ParseHeader (lldb_private::DataExtractor &data,
- llvm::MachO::fat_header &header,
- std::vector<llvm::MachO::fat_arch> &fat_archs);
+ llvm::MachO::fat_header m_header;
+ std::vector<llvm::MachO::fat_arch> m_fat_archs;
+
+ static bool ParseHeader(lldb_private::DataExtractor &data,
+ llvm::MachO::fat_header &header,
+ std::vector<llvm::MachO::fat_arch> &fat_archs);
};
#endif // liblldb_ObjectContainerUniversalMachO_h_
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp Tue Sep 6 15:57:50 2016
@@ -24,240 +24,201 @@ using namespace llvm::ELF;
//
// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
// with error handling code and provide for parsing a sequence of values.
-static bool
-GetMaxU64(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset,
- uint64_t *value,
- uint32_t byte_size)
-{
- const lldb::offset_t saved_offset = *offset;
- *value = data.GetMaxU64(offset, byte_size);
- return *offset != saved_offset;
-}
-
-static bool
-GetMaxU64(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset,
- uint64_t *value,
- uint32_t byte_size,
- uint32_t count)
-{
- lldb::offset_t saved_offset = *offset;
-
- for (uint32_t i = 0; i < count; ++i, ++value)
- {
- if (GetMaxU64(data, offset, value, byte_size) == false)
- {
- *offset = saved_offset;
- return false;
- }
+static bool GetMaxU64(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset, uint64_t *value,
+ uint32_t byte_size) {
+ const lldb::offset_t saved_offset = *offset;
+ *value = data.GetMaxU64(offset, byte_size);
+ return *offset != saved_offset;
+}
+
+static bool GetMaxU64(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset, uint64_t *value,
+ uint32_t byte_size, uint32_t count) {
+ lldb::offset_t saved_offset = *offset;
+
+ for (uint32_t i = 0; i < count; ++i, ++value) {
+ if (GetMaxU64(data, offset, value, byte_size) == false) {
+ *offset = saved_offset;
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool GetMaxS64(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset, int64_t *value,
+ uint32_t byte_size) {
+ const lldb::offset_t saved_offset = *offset;
+ *value = data.GetMaxS64(offset, byte_size);
+ return *offset != saved_offset;
+}
+
+static bool GetMaxS64(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset, int64_t *value,
+ uint32_t byte_size, uint32_t count) {
+ lldb::offset_t saved_offset = *offset;
+
+ for (uint32_t i = 0; i < count; ++i, ++value) {
+ if (GetMaxS64(data, offset, value, byte_size) == false) {
+ *offset = saved_offset;
+ return false;
}
- return true;
-}
-
-static bool
-GetMaxS64(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset,
- int64_t *value,
- uint32_t byte_size)
-{
- const lldb::offset_t saved_offset = *offset;
- *value = data.GetMaxS64(offset, byte_size);
- return *offset != saved_offset;
-}
-
-static bool
-GetMaxS64(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset,
- int64_t *value,
- uint32_t byte_size,
- uint32_t count)
-{
- lldb::offset_t saved_offset = *offset;
-
- for (uint32_t i = 0; i < count; ++i, ++value)
- {
- if (GetMaxS64(data, offset, value, byte_size) == false)
- {
- *offset = saved_offset;
- return false;
- }
- }
- return true;
+ }
+ return true;
}
//------------------------------------------------------------------------------
// ELFHeader
-ELFHeader::ELFHeader()
-{
- memset(this, 0, sizeof(ELFHeader));
-}
-
-ByteOrder
-ELFHeader::GetByteOrder() const
-{
- if (e_ident[EI_DATA] == ELFDATA2MSB)
- return eByteOrderBig;
- if (e_ident[EI_DATA] == ELFDATA2LSB)
- return eByteOrderLittle;
- return eByteOrderInvalid;
-}
-
-bool
-ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- // Read e_ident. This provides byte order and address size info.
- if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
- return false;
-
- const unsigned byte_size = Is32Bit() ? 4 : 8;
- data.SetByteOrder(GetByteOrder());
- data.SetAddressByteSize(byte_size);
-
- // Read e_type and e_machine.
- if (data.GetU16(offset, &e_type, 2) == NULL)
- return false;
-
- // Read e_version.
- if (data.GetU32(offset, &e_version, 1) == NULL)
- return false;
-
- // Read e_entry, e_phoff and e_shoff.
- if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
- return false;
-
- // Read e_flags.
- if (data.GetU32(offset, &e_flags, 1) == NULL)
- return false;
-
- // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
- // e_shstrndx.
- if (data.GetU16(offset, &e_ehsize, 6) == NULL)
- return false;
-
- return true;
-}
-
-bool
-ELFHeader::MagicBytesMatch(const uint8_t *magic)
-{
- return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
-}
-
-unsigned
-ELFHeader::AddressSizeInBytes(const uint8_t *magic)
-{
- unsigned address_size = 0;
-
- switch (magic[EI_CLASS])
- {
- case ELFCLASS32:
- address_size = 4;
- break;
-
- case ELFCLASS64:
- address_size = 8;
- break;
- }
- return address_size;
-}
+ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
-unsigned
-ELFHeader::GetRelocationJumpSlotType() const
-{
- unsigned slot = 0;
-
- switch (e_machine)
- {
- default:
- assert(false && "architecture not supported");
- break;
- case EM_PPC:
- slot = R_PPC_JMP_SLOT;
- break;
- case EM_PPC64:
- slot = R_PPC64_JMP_SLOT;
- break;
- case EM_386:
- case EM_IAMCU: // FIXME: is this correct?
- slot = R_386_JUMP_SLOT;
- break;
- case EM_X86_64:
- slot = R_X86_64_JUMP_SLOT;
- break;
- case EM_ARM:
- slot = R_ARM_JUMP_SLOT;
- break;
- case EM_HEXAGON:
- slot = R_HEX_JMP_SLOT;
- break;
- case EM_AARCH64:
- slot = R_AARCH64_JUMP_SLOT;
- break;
- case EM_MIPS:
- slot = R_MIPS_JUMP_SLOT;
- break;
- case EM_S390:
- slot = R_390_JMP_SLOT;
- break;
- }
+ByteOrder ELFHeader::GetByteOrder() const {
+ if (e_ident[EI_DATA] == ELFDATA2MSB)
+ return eByteOrderBig;
+ if (e_ident[EI_DATA] == ELFDATA2LSB)
+ return eByteOrderLittle;
+ return eByteOrderInvalid;
+}
+
+bool ELFHeader::Parse(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ // Read e_ident. This provides byte order and address size info.
+ if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
+ return false;
+
+ const unsigned byte_size = Is32Bit() ? 4 : 8;
+ data.SetByteOrder(GetByteOrder());
+ data.SetAddressByteSize(byte_size);
+
+ // Read e_type and e_machine.
+ if (data.GetU16(offset, &e_type, 2) == NULL)
+ return false;
+
+ // Read e_version.
+ if (data.GetU32(offset, &e_version, 1) == NULL)
+ return false;
+
+ // Read e_entry, e_phoff and e_shoff.
+ if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
+ return false;
+
+ // Read e_flags.
+ if (data.GetU32(offset, &e_flags, 1) == NULL)
+ return false;
+
+ // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
+ // e_shstrndx.
+ if (data.GetU16(offset, &e_ehsize, 6) == NULL)
+ return false;
+
+ return true;
+}
+
+bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
+ return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
+}
+
+unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
+ unsigned address_size = 0;
+
+ switch (magic[EI_CLASS]) {
+ case ELFCLASS32:
+ address_size = 4;
+ break;
+
+ case ELFCLASS64:
+ address_size = 8;
+ break;
+ }
+ return address_size;
+}
+
+unsigned ELFHeader::GetRelocationJumpSlotType() const {
+ unsigned slot = 0;
+
+ switch (e_machine) {
+ default:
+ assert(false && "architecture not supported");
+ break;
+ case EM_PPC:
+ slot = R_PPC_JMP_SLOT;
+ break;
+ case EM_PPC64:
+ slot = R_PPC64_JMP_SLOT;
+ break;
+ case EM_386:
+ case EM_IAMCU: // FIXME: is this correct?
+ slot = R_386_JUMP_SLOT;
+ break;
+ case EM_X86_64:
+ slot = R_X86_64_JUMP_SLOT;
+ break;
+ case EM_ARM:
+ slot = R_ARM_JUMP_SLOT;
+ break;
+ case EM_HEXAGON:
+ slot = R_HEX_JMP_SLOT;
+ break;
+ case EM_AARCH64:
+ slot = R_AARCH64_JUMP_SLOT;
+ break;
+ case EM_MIPS:
+ slot = R_MIPS_JUMP_SLOT;
+ break;
+ case EM_S390:
+ slot = R_390_JMP_SLOT;
+ break;
+ }
- return slot;
+ return slot;
}
//------------------------------------------------------------------------------
// ELFSectionHeader
-ELFSectionHeader::ELFSectionHeader()
-{
- memset(this, 0, sizeof(ELFSectionHeader));
-}
-
-bool
-ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset)
-{
- const unsigned byte_size = data.GetAddressByteSize();
-
- // Read sh_name and sh_type.
- if (data.GetU32(offset, &sh_name, 2) == NULL)
- return false;
-
- // Read sh_flags.
- if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
- return false;
-
- // Read sh_addr, sh_off and sh_size.
- if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
- return false;
-
- // Read sh_link and sh_info.
- if (data.GetU32(offset, &sh_link, 2) == NULL)
- return false;
-
- // Read sh_addralign and sh_entsize.
- if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
- return false;
+ELFSectionHeader::ELFSectionHeader() {
+ memset(this, 0, sizeof(ELFSectionHeader));
+}
+
+bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const unsigned byte_size = data.GetAddressByteSize();
- return true;
+ // Read sh_name and sh_type.
+ if (data.GetU32(offset, &sh_name, 2) == NULL)
+ return false;
+
+ // Read sh_flags.
+ if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
+ return false;
+
+ // Read sh_addr, sh_off and sh_size.
+ if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
+ return false;
+
+ // Read sh_link and sh_info.
+ if (data.GetU32(offset, &sh_link, 2) == NULL)
+ return false;
+
+ // Read sh_addralign and sh_entsize.
+ if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
+ return false;
+
+ return true;
}
//------------------------------------------------------------------------------
// ELFSymbol
-ELFSymbol::ELFSymbol()
-{
- memset(this, 0, sizeof(ELFSymbol));
-}
+ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
-#define ENUM_TO_CSTR(e) case e: return #e
-
-const char *
-ELFSymbol::bindingToCString(unsigned char binding)
-{
- switch (binding)
- {
+#define ENUM_TO_CSTR(e) \
+ case e: \
+ return #e
+
+const char *ELFSymbol::bindingToCString(unsigned char binding) {
+ switch (binding) {
ENUM_TO_CSTR(STB_LOCAL);
ENUM_TO_CSTR(STB_GLOBAL);
ENUM_TO_CSTR(STB_WEAK);
@@ -265,15 +226,12 @@ ELFSymbol::bindingToCString(unsigned cha
ENUM_TO_CSTR(STB_HIOS);
ENUM_TO_CSTR(STB_LOPROC);
ENUM_TO_CSTR(STB_HIPROC);
- }
- return "";
+ }
+ return "";
}
-const char *
-ELFSymbol::typeToCString(unsigned char type)
-{
- switch (type)
- {
+const char *ELFSymbol::typeToCString(unsigned char type) {
+ switch (type) {
ENUM_TO_CSTR(STT_NOTYPE);
ENUM_TO_CSTR(STT_OBJECT);
ENUM_TO_CSTR(STT_FUNC);
@@ -285,16 +243,13 @@ ELFSymbol::typeToCString(unsigned char t
ENUM_TO_CSTR(STT_HIOS);
ENUM_TO_CSTR(STT_LOPROC);
ENUM_TO_CSTR(STT_HIPROC);
- }
- return "";
+ }
+ return "";
}
-const char *
-ELFSymbol::sectionIndexToCString (elf_half shndx,
- const lldb_private::SectionList *section_list)
-{
- switch (shndx)
- {
+const char *ELFSymbol::sectionIndexToCString(
+ elf_half shndx, const lldb_private::SectionList *section_list) {
+ switch (shndx) {
ENUM_TO_CSTR(SHN_UNDEF);
ENUM_TO_CSTR(SHN_LOPROC);
ENUM_TO_CSTR(SHN_HIPROC);
@@ -303,180 +258,148 @@ ELFSymbol::sectionIndexToCString (elf_ha
ENUM_TO_CSTR(SHN_ABS);
ENUM_TO_CSTR(SHN_COMMON);
ENUM_TO_CSTR(SHN_XINDEX);
- default:
- {
- const lldb_private::Section *section = section_list->GetSectionAtIndex(shndx).get();
- if (section)
- return section->GetName().AsCString("");
- }
- break;
- }
- return "";
-}
-
-void
-ELFSymbol::Dump (lldb_private::Stream *s,
- uint32_t idx,
- const lldb_private::DataExtractor *strtab_data,
- const lldb_private::SectionList *section_list)
-{
- s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
- idx,
- st_value,
- st_size,
- st_name,
- st_info,
- bindingToCString (getBinding()),
- typeToCString (getType()),
- st_other,
- st_shndx,
- sectionIndexToCString (st_shndx, section_list),
- strtab_data ? strtab_data->PeekCStr(st_name) : "");
-}
-
-bool
-ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- const unsigned byte_size = data.GetAddressByteSize();
- const bool parsing_32 = byte_size == 4;
-
- // Read st_name.
- if (data.GetU32(offset, &st_name, 1) == NULL)
- return false;
-
- if (parsing_32)
- {
- // Read st_value and st_size.
- if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
- return false;
-
- // Read st_info and st_other.
- if (data.GetU8(offset, &st_info, 2) == NULL)
- return false;
-
- // Read st_shndx.
- if (data.GetU16(offset, &st_shndx, 1) == NULL)
- return false;
- }
- else
- {
- // Read st_info and st_other.
- if (data.GetU8(offset, &st_info, 2) == NULL)
- return false;
-
- // Read st_shndx.
- if (data.GetU16(offset, &st_shndx, 1) == NULL)
- return false;
-
- // Read st_value and st_size.
- if (data.GetU64(offset, &st_value, 2) == NULL)
- return false;
- }
- return true;
+ default: {
+ const lldb_private::Section *section =
+ section_list->GetSectionAtIndex(shndx).get();
+ if (section)
+ return section->GetName().AsCString("");
+ } break;
+ }
+ return "";
+}
+
+void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx,
+ const lldb_private::DataExtractor *strtab_data,
+ const lldb_private::SectionList *section_list) {
+ s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
+ " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
+ idx, st_value, st_size, st_name, st_info,
+ bindingToCString(getBinding()), typeToCString(getType()), st_other,
+ st_shndx, sectionIndexToCString(st_shndx, section_list),
+ strtab_data ? strtab_data->PeekCStr(st_name) : "");
+}
+
+bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const unsigned byte_size = data.GetAddressByteSize();
+ const bool parsing_32 = byte_size == 4;
+
+ // Read st_name.
+ if (data.GetU32(offset, &st_name, 1) == NULL)
+ return false;
+
+ if (parsing_32) {
+ // Read st_value and st_size.
+ if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
+ return false;
+
+ // Read st_info and st_other.
+ if (data.GetU8(offset, &st_info, 2) == NULL)
+ return false;
+
+ // Read st_shndx.
+ if (data.GetU16(offset, &st_shndx, 1) == NULL)
+ return false;
+ } else {
+ // Read st_info and st_other.
+ if (data.GetU8(offset, &st_info, 2) == NULL)
+ return false;
+
+ // Read st_shndx.
+ if (data.GetU16(offset, &st_shndx, 1) == NULL)
+ return false;
+
+ // Read st_value and st_size.
+ if (data.GetU64(offset, &st_value, 2) == NULL)
+ return false;
+ }
+ return true;
}
//------------------------------------------------------------------------------
// ELFProgramHeader
-ELFProgramHeader::ELFProgramHeader()
-{
- memset(this, 0, sizeof(ELFProgramHeader));
-}
-
-bool
-ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
- lldb::offset_t *offset)
-{
- const uint32_t byte_size = data.GetAddressByteSize();
- const bool parsing_32 = byte_size == 4;
-
- // Read p_type;
- if (data.GetU32(offset, &p_type, 1) == NULL)
- return false;
-
- if (parsing_32) {
- // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
- return false;
-
- // Read p_flags.
- if (data.GetU32(offset, &p_flags, 1) == NULL)
- return false;
-
- // Read p_align.
- if (GetMaxU64(data, offset, &p_align, byte_size) == false)
- return false;
- }
- else {
- // Read p_flags.
- if (data.GetU32(offset, &p_flags, 1) == NULL)
- return false;
-
- // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
- return false;
- }
+ELFProgramHeader::ELFProgramHeader() {
+ memset(this, 0, sizeof(ELFProgramHeader));
+}
+
+bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const uint32_t byte_size = data.GetAddressByteSize();
+ const bool parsing_32 = byte_size == 4;
+
+ // Read p_type;
+ if (data.GetU32(offset, &p_type, 1) == NULL)
+ return false;
+
+ if (parsing_32) {
+ // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
+ if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
+ return false;
+
+ // Read p_flags.
+ if (data.GetU32(offset, &p_flags, 1) == NULL)
+ return false;
+
+ // Read p_align.
+ if (GetMaxU64(data, offset, &p_align, byte_size) == false)
+ return false;
+ } else {
+ // Read p_flags.
+ if (data.GetU32(offset, &p_flags, 1) == NULL)
+ return false;
+
+ // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
+ if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
+ return false;
+ }
- return true;
+ return true;
}
//------------------------------------------------------------------------------
// ELFDynamic
-ELFDynamic::ELFDynamic()
-{
- memset(this, 0, sizeof(ELFDynamic));
-}
+ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
-bool
-ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- const unsigned byte_size = data.GetAddressByteSize();
- return GetMaxS64(data, offset, &d_tag, byte_size, 2);
+bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const unsigned byte_size = data.GetAddressByteSize();
+ return GetMaxS64(data, offset, &d_tag, byte_size, 2);
}
//------------------------------------------------------------------------------
// ELFRel
-ELFRel::ELFRel()
-{
- memset(this, 0, sizeof(ELFRel));
-}
+ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
-bool
-ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- const unsigned byte_size = data.GetAddressByteSize();
+bool ELFRel::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const unsigned byte_size = data.GetAddressByteSize();
- // Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
- return false;
+ // Read r_offset and r_info.
+ if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+ return false;
- return true;
+ return true;
}
//------------------------------------------------------------------------------
// ELFRela
-ELFRela::ELFRela()
-{
- memset(this, 0, sizeof(ELFRela));
-}
+ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
-bool
-ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- const unsigned byte_size = data.GetAddressByteSize();
+bool ELFRela::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ const unsigned byte_size = data.GetAddressByteSize();
- // Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
- return false;
+ // Read r_offset and r_info.
+ if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+ return false;
- // Read r_addend;
- if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
- return false;
+ // Read r_addend;
+ if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
+ return false;
- return true;
+ return true;
}
-
-
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.h Tue Sep 6 15:57:50 2016
@@ -25,13 +25,11 @@
#include "lldb/lldb-enumerations.h"
-namespace lldb_private
-{
+namespace lldb_private {
class DataExtractor;
} // End namespace lldb_private.
-namespace elf
-{
+namespace elf {
//------------------------------------------------------------------------------
/// @name ELF type definitions.
@@ -44,10 +42,10 @@ typedef uint64_t elf_addr;
typedef uint64_t elf_off;
typedef uint16_t elf_half;
typedef uint32_t elf_word;
-typedef int32_t elf_sword;
+typedef int32_t elf_sword;
typedef uint64_t elf_size;
typedef uint64_t elf_xword;
-typedef int64_t elf_sxword;
+typedef int64_t elf_sxword;
//@}
//------------------------------------------------------------------------------
@@ -56,376 +54,331 @@ typedef int64_t elf_sxword;
///
/// This object is used to identify the general attributes on an ELF file and to
/// locate additional sections within the file.
-struct ELFHeader
-{
- unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.
- elf_addr e_entry; ///< Virtual address program entry point.
- elf_off e_phoff; ///< File offset of program header table.
- elf_off e_shoff; ///< File offset of section header table.
- elf_word e_flags; ///< Processor specific flags.
- elf_word e_version; ///< Version of object file (always 1).
- elf_half e_type; ///< Object file type.
- elf_half e_machine; ///< Target architecture.
- elf_half e_ehsize; ///< Byte size of the ELF header.
- elf_half e_phentsize; ///< Size of a program header table entry.
- elf_half e_phnum; ///< Number of program header entries.
- elf_half e_shentsize; ///< Size of a section header table entry.
- elf_half e_shnum; ///< Number of section header entries.
- elf_half e_shstrndx; ///< String table section index.
-
- ELFHeader();
-
- //--------------------------------------------------------------------------
- /// Returns true if this is a 32 bit ELF file header.
- ///
- /// @return
- /// True if this is a 32 bit ELF file header.
- bool Is32Bit() const {
- return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32;
- }
-
- //--------------------------------------------------------------------------
- /// Returns true if this is a 64 bit ELF file header.
- ///
- /// @return
- /// True if this is a 64 bit ELF file header.
- bool Is64Bit() const {
- return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;
- }
-
- //--------------------------------------------------------------------------
- /// The byte order of this ELF file header.
- ///
- /// @return
- /// The byte order of this ELF file as described by the header.
- lldb::ByteOrder
- GetByteOrder() const;
-
- //--------------------------------------------------------------------------
- /// The jump slot relocation type of this ELF.
- unsigned
- GetRelocationJumpSlotType() const;
-
- //--------------------------------------------------------------------------
- /// Parse an ELFHeader entry starting at position \p offset and
- /// update the data extractor with the address size and byte order
- /// attributes as defined by the header.
- ///
- /// @param[in,out] data
- /// The DataExtractor to read from. Updated with the address size and
- /// byte order attributes appropriate to this header.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFHeader was successfully read and false
- /// otherwise.
- bool
- Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
- //--------------------------------------------------------------------------
- /// Examines at most EI_NIDENT bytes starting from the given pointer and
- /// determines if the magic ELF identification exists.
- ///
- /// @return
- /// True if the given sequence of bytes identifies an ELF file.
- static bool
- MagicBytesMatch(const uint8_t *magic);
-
- //--------------------------------------------------------------------------
- /// Examines at most EI_NIDENT bytes starting from the given address and
- /// determines the address size of the underlying ELF file. This function
- /// should only be called on an pointer for which MagicBytesMatch returns
- /// true.
- ///
- /// @return
- /// The number of bytes forming an address in the ELF file (either 4 or
- /// 8), else zero if the address size could not be determined.
- static unsigned
- AddressSizeInBytes(const uint8_t *magic);
+struct ELFHeader {
+ unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.
+ elf_addr e_entry; ///< Virtual address program entry point.
+ elf_off e_phoff; ///< File offset of program header table.
+ elf_off e_shoff; ///< File offset of section header table.
+ elf_word e_flags; ///< Processor specific flags.
+ elf_word e_version; ///< Version of object file (always 1).
+ elf_half e_type; ///< Object file type.
+ elf_half e_machine; ///< Target architecture.
+ elf_half e_ehsize; ///< Byte size of the ELF header.
+ elf_half e_phentsize; ///< Size of a program header table entry.
+ elf_half e_phnum; ///< Number of program header entries.
+ elf_half e_shentsize; ///< Size of a section header table entry.
+ elf_half e_shnum; ///< Number of section header entries.
+ elf_half e_shstrndx; ///< String table section index.
+
+ ELFHeader();
+
+ //--------------------------------------------------------------------------
+ /// Returns true if this is a 32 bit ELF file header.
+ ///
+ /// @return
+ /// True if this is a 32 bit ELF file header.
+ bool Is32Bit() const {
+ return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32;
+ }
+
+ //--------------------------------------------------------------------------
+ /// Returns true if this is a 64 bit ELF file header.
+ ///
+ /// @return
+ /// True if this is a 64 bit ELF file header.
+ bool Is64Bit() const {
+ return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;
+ }
+
+ //--------------------------------------------------------------------------
+ /// The byte order of this ELF file header.
+ ///
+ /// @return
+ /// The byte order of this ELF file as described by the header.
+ lldb::ByteOrder GetByteOrder() const;
+
+ //--------------------------------------------------------------------------
+ /// The jump slot relocation type of this ELF.
+ unsigned GetRelocationJumpSlotType() const;
+
+ //--------------------------------------------------------------------------
+ /// Parse an ELFHeader entry starting at position \p offset and
+ /// update the data extractor with the address size and byte order
+ /// attributes as defined by the header.
+ ///
+ /// @param[in,out] data
+ /// The DataExtractor to read from. Updated with the address size and
+ /// byte order attributes appropriate to this header.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFHeader was successfully read and false
+ /// otherwise.
+ bool Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ //--------------------------------------------------------------------------
+ /// Examines at most EI_NIDENT bytes starting from the given pointer and
+ /// determines if the magic ELF identification exists.
+ ///
+ /// @return
+ /// True if the given sequence of bytes identifies an ELF file.
+ static bool MagicBytesMatch(const uint8_t *magic);
+
+ //--------------------------------------------------------------------------
+ /// Examines at most EI_NIDENT bytes starting from the given address and
+ /// determines the address size of the underlying ELF file. This function
+ /// should only be called on an pointer for which MagicBytesMatch returns
+ /// true.
+ ///
+ /// @return
+ /// The number of bytes forming an address in the ELF file (either 4 or
+ /// 8), else zero if the address size could not be determined.
+ static unsigned AddressSizeInBytes(const uint8_t *magic);
};
//------------------------------------------------------------------------------
/// @class ELFSectionHeader
/// @brief Generic representation of an ELF section header.
-struct ELFSectionHeader
-{
- elf_word sh_name; ///< Section name string index.
- elf_word sh_type; ///< Section type.
- elf_xword sh_flags; ///< Section attributes.
- elf_addr sh_addr; ///< Virtual address of the section in memory.
- elf_off sh_offset; ///< Start of section from beginning of file.
- elf_xword sh_size; ///< Number of bytes occupied in the file.
- elf_word sh_link; ///< Index of associated section.
- elf_word sh_info; ///< Extra section info (overloaded).
- elf_xword sh_addralign; ///< Power of two alignment constraint.
- elf_xword sh_entsize; ///< Byte size of each section entry.
-
- ELFSectionHeader();
-
- //--------------------------------------------------------------------------
- /// Parse an ELFSectionHeader entry from the given DataExtracter starting at
- /// position \p offset.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFSectionHeader was successfully read and false
- /// otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+struct ELFSectionHeader {
+ elf_word sh_name; ///< Section name string index.
+ elf_word sh_type; ///< Section type.
+ elf_xword sh_flags; ///< Section attributes.
+ elf_addr sh_addr; ///< Virtual address of the section in memory.
+ elf_off sh_offset; ///< Start of section from beginning of file.
+ elf_xword sh_size; ///< Number of bytes occupied in the file.
+ elf_word sh_link; ///< Index of associated section.
+ elf_word sh_info; ///< Extra section info (overloaded).
+ elf_xword sh_addralign; ///< Power of two alignment constraint.
+ elf_xword sh_entsize; ///< Byte size of each section entry.
+
+ ELFSectionHeader();
+
+ //--------------------------------------------------------------------------
+ /// Parse an ELFSectionHeader entry from the given DataExtracter starting at
+ /// position \p offset.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFSectionHeader was successfully read and false
+ /// otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
/// @class ELFProgramHeader
/// @brief Generic representation of an ELF program header.
-struct ELFProgramHeader
-{
- elf_word p_type; ///< Type of program segment.
- elf_word p_flags; ///< Segment attributes.
- elf_off p_offset; ///< Start of segment from beginning of file.
- elf_addr p_vaddr; ///< Virtual address of segment in memory.
- elf_addr p_paddr; ///< Physical address (for non-VM systems).
- elf_xword p_filesz; ///< Byte size of the segment in file.
- elf_xword p_memsz; ///< Byte size of the segment in memory.
- elf_xword p_align; ///< Segment alignment constraint.
-
- ELFProgramHeader();
-
- /// Parse an ELFProgramHeader entry from the given DataExtractor starting at
- /// position \p offset. The address size of the DataExtractor determines if
- /// a 32 or 64 bit object is to be parsed.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFProgramHeader was successfully read and false
- /// otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+struct ELFProgramHeader {
+ elf_word p_type; ///< Type of program segment.
+ elf_word p_flags; ///< Segment attributes.
+ elf_off p_offset; ///< Start of segment from beginning of file.
+ elf_addr p_vaddr; ///< Virtual address of segment in memory.
+ elf_addr p_paddr; ///< Physical address (for non-VM systems).
+ elf_xword p_filesz; ///< Byte size of the segment in file.
+ elf_xword p_memsz; ///< Byte size of the segment in memory.
+ elf_xword p_align; ///< Segment alignment constraint.
+
+ ELFProgramHeader();
+
+ /// Parse an ELFProgramHeader entry from the given DataExtractor starting at
+ /// position \p offset. The address size of the DataExtractor determines if
+ /// a 32 or 64 bit object is to be parsed.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFProgramHeader was successfully read and false
+ /// otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
/// @class ELFSymbol
/// @brief Represents a symbol within an ELF symbol table.
-struct ELFSymbol
-{
- elf_addr st_value; ///< Absolute or relocatable address.
- elf_xword st_size; ///< Size of the symbol or zero.
- elf_word st_name; ///< Symbol name string index.
- unsigned char st_info; ///< Symbol type and binding attributes.
- unsigned char st_other; ///< Reserved for future use.
- elf_half st_shndx; ///< Section to which this symbol applies.
-
- ELFSymbol();
-
- /// Returns the binding attribute of the st_info member.
- unsigned char getBinding() const { return st_info >> 4; }
-
- /// Returns the type attribute of the st_info member.
- unsigned char getType() const { return st_info & 0x0F; }
-
- /// Sets the binding and type of the st_info member.
- void setBindingAndType(unsigned char binding, unsigned char type) {
- st_info = (binding << 4) + (type & 0x0F);
- }
-
- static const char *
- bindingToCString(unsigned char binding);
-
- static const char *
- typeToCString(unsigned char type);
-
- static const char *
- sectionIndexToCString(elf_half shndx,
- const lldb_private::SectionList *section_list);
-
- /// Parse an ELFSymbol entry from the given DataExtractor starting at
- /// position \p offset. The address size of the DataExtractor determines if
- /// a 32 or 64 bit object is to be parsed.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFSymbol was successfully read and false otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
- void
- Dump (lldb_private::Stream *s,
- uint32_t idx,
- const lldb_private::DataExtractor *strtab_data,
- const lldb_private::SectionList *section_list);
+struct ELFSymbol {
+ elf_addr st_value; ///< Absolute or relocatable address.
+ elf_xword st_size; ///< Size of the symbol or zero.
+ elf_word st_name; ///< Symbol name string index.
+ unsigned char st_info; ///< Symbol type and binding attributes.
+ unsigned char st_other; ///< Reserved for future use.
+ elf_half st_shndx; ///< Section to which this symbol applies.
+
+ ELFSymbol();
+
+ /// Returns the binding attribute of the st_info member.
+ unsigned char getBinding() const { return st_info >> 4; }
+
+ /// Returns the type attribute of the st_info member.
+ unsigned char getType() const { return st_info & 0x0F; }
+
+ /// Sets the binding and type of the st_info member.
+ void setBindingAndType(unsigned char binding, unsigned char type) {
+ st_info = (binding << 4) + (type & 0x0F);
+ }
+
+ static const char *bindingToCString(unsigned char binding);
+
+ static const char *typeToCString(unsigned char type);
+
+ static const char *
+ sectionIndexToCString(elf_half shndx,
+ const lldb_private::SectionList *section_list);
+
+ /// Parse an ELFSymbol entry from the given DataExtractor starting at
+ /// position \p offset. The address size of the DataExtractor determines if
+ /// a 32 or 64 bit object is to be parsed.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFSymbol was successfully read and false otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ void Dump(lldb_private::Stream *s, uint32_t idx,
+ const lldb_private::DataExtractor *strtab_data,
+ const lldb_private::SectionList *section_list);
};
//------------------------------------------------------------------------------
/// @class ELFDynamic
/// @brief Represents an entry in an ELF dynamic table.
-struct ELFDynamic
-{
- elf_sxword d_tag; ///< Type of dynamic table entry.
- union
- {
- elf_xword d_val; ///< Integer value of the table entry.
- elf_addr d_ptr; ///< Pointer value of the table entry.
- };
-
- ELFDynamic();
-
- /// Parse an ELFDynamic entry from the given DataExtractor starting at
- /// position \p offset. The address size of the DataExtractor determines if
- /// a 32 or 64 bit object is to be parsed.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFDynamic entry was successfully read and false
- /// otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+struct ELFDynamic {
+ elf_sxword d_tag; ///< Type of dynamic table entry.
+ union {
+ elf_xword d_val; ///< Integer value of the table entry.
+ elf_addr d_ptr; ///< Pointer value of the table entry.
+ };
+
+ ELFDynamic();
+
+ /// Parse an ELFDynamic entry from the given DataExtractor starting at
+ /// position \p offset. The address size of the DataExtractor determines if
+ /// a 32 or 64 bit object is to be parsed.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFDynamic entry was successfully read and false
+ /// otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
};
//------------------------------------------------------------------------------
/// @class ELFRel
/// @brief Represents a relocation entry with an implicit addend.
-struct ELFRel
-{
- elf_addr r_offset; ///< Address of reference.
- elf_xword r_info; ///< symbol index and type of relocation.
-
- ELFRel();
-
- /// Parse an ELFRel entry from the given DataExtractor starting at position
- /// \p offset. The address size of the DataExtractor determines if a 32 or
- /// 64 bit object is to be parsed.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFRel entry was successfully read and false otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
- /// Returns the type when the given entry represents a 32-bit relocation.
- static unsigned
- RelocType32(const ELFRel &rel)
- {
- return rel.r_info & 0x0ff;
- }
-
- /// Returns the type when the given entry represents a 64-bit relocation.
- static unsigned
- RelocType64(const ELFRel &rel)
- {
- return rel.r_info & 0xffffffff;
- }
-
- /// Returns the symbol index when the given entry represents a 32-bit
- /// relocation.
- static unsigned
- RelocSymbol32(const ELFRel &rel)
- {
- return rel.r_info >> 8;
- }
-
- /// Returns the symbol index when the given entry represents a 64-bit
- /// relocation.
- static unsigned
- RelocSymbol64(const ELFRel &rel)
- {
- return rel.r_info >> 32;
- }
+struct ELFRel {
+ elf_addr r_offset; ///< Address of reference.
+ elf_xword r_info; ///< symbol index and type of relocation.
+
+ ELFRel();
+
+ /// Parse an ELFRel entry from the given DataExtractor starting at position
+ /// \p offset. The address size of the DataExtractor determines if a 32 or
+ /// 64 bit object is to be parsed.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFRel entry was successfully read and false otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ /// Returns the type when the given entry represents a 32-bit relocation.
+ static unsigned RelocType32(const ELFRel &rel) { return rel.r_info & 0x0ff; }
+
+ /// Returns the type when the given entry represents a 64-bit relocation.
+ static unsigned RelocType64(const ELFRel &rel) {
+ return rel.r_info & 0xffffffff;
+ }
+
+ /// Returns the symbol index when the given entry represents a 32-bit
+ /// relocation.
+ static unsigned RelocSymbol32(const ELFRel &rel) { return rel.r_info >> 8; }
+
+ /// Returns the symbol index when the given entry represents a 64-bit
+ /// relocation.
+ static unsigned RelocSymbol64(const ELFRel &rel) { return rel.r_info >> 32; }
};
//------------------------------------------------------------------------------
/// @class ELFRela
/// @brief Represents a relocation entry with an explicit addend.
-struct ELFRela
-{
- elf_addr r_offset; ///< Address of reference.
- elf_xword r_info; ///< Symbol index and type of relocation.
- elf_sxword r_addend; ///< Constant part of expression.
-
- ELFRela();
-
- /// Parse an ELFRela entry from the given DataExtractor starting at position
- /// \p offset. The address size of the DataExtractor determines if a 32 or
- /// 64 bit object is to be parsed.
- ///
- /// @param[in] data
- /// The DataExtractor to read from. The address size of the extractor
- /// determines if a 32 or 64 bit object should be read.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFRela entry was successfully read and false otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
- /// Returns the type when the given entry represents a 32-bit relocation.
- static unsigned
- RelocType32(const ELFRela &rela)
- {
- return rela.r_info & 0x0ff;
- }
-
- /// Returns the type when the given entry represents a 64-bit relocation.
- static unsigned
- RelocType64(const ELFRela &rela)
- {
- return rela.r_info & 0xffffffff;
- }
-
- /// Returns the symbol index when the given entry represents a 32-bit
- /// relocation.
- static unsigned
- RelocSymbol32(const ELFRela &rela)
- {
- return rela.r_info >> 8;
- }
-
- /// Returns the symbol index when the given entry represents a 64-bit
- /// relocation.
- static unsigned
- RelocSymbol64(const ELFRela &rela)
- {
- return rela.r_info >> 32;
- }
+struct ELFRela {
+ elf_addr r_offset; ///< Address of reference.
+ elf_xword r_info; ///< Symbol index and type of relocation.
+ elf_sxword r_addend; ///< Constant part of expression.
+
+ ELFRela();
+
+ /// Parse an ELFRela entry from the given DataExtractor starting at position
+ /// \p offset. The address size of the DataExtractor determines if a 32 or
+ /// 64 bit object is to be parsed.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from. The address size of the extractor
+ /// determines if a 32 or 64 bit object should be read.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFRela entry was successfully read and false otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ /// Returns the type when the given entry represents a 32-bit relocation.
+ static unsigned RelocType32(const ELFRela &rela) {
+ return rela.r_info & 0x0ff;
+ }
+
+ /// Returns the type when the given entry represents a 64-bit relocation.
+ static unsigned RelocType64(const ELFRela &rela) {
+ return rela.r_info & 0xffffffff;
+ }
+
+ /// Returns the symbol index when the given entry represents a 32-bit
+ /// relocation.
+ static unsigned RelocSymbol32(const ELFRela &rela) {
+ return rela.r_info >> 8;
+ }
+
+ /// Returns the symbol index when the given entry represents a 64-bit
+ /// relocation.
+ static unsigned RelocSymbol64(const ELFRela &rela) {
+ return rela.r_info >> 32;
+ }
};
} // End namespace elf.
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Tue Sep 6 15:57:50 2016
@@ -9,8 +9,8 @@
#include "ObjectFileELF.h"
-#include <cassert>
#include <algorithm>
+#include <cassert>
#include <unordered_map>
#include "lldb/Core/ArchSpec.h"
@@ -35,8 +35,10 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MipsABIFlags.h"
-#define CASE_AND_STREAM(s, def, width) \
- case def: s->Printf("%-*s", width, #def); break;
+#define CASE_AND_STREAM(s, def, width) \
+ case def: \
+ s->Printf("%-*s", width, #def); \
+ break;
using namespace lldb;
using namespace lldb_private;
@@ -47,64 +49,64 @@ namespace {
// ELF note owner definitions
const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
-const char *const LLDB_NT_OWNER_GNU = "GNU";
-const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
-const char *const LLDB_NT_OWNER_CSR = "csr";
+const char *const LLDB_NT_OWNER_GNU = "GNU";
+const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
+const char *const LLDB_NT_OWNER_CSR = "csr";
const char *const LLDB_NT_OWNER_ANDROID = "Android";
-const char *const LLDB_NT_OWNER_CORE = "CORE";
-const char *const LLDB_NT_OWNER_LINUX = "LINUX";
+const char *const LLDB_NT_OWNER_CORE = "CORE";
+const char *const LLDB_NT_OWNER_LINUX = "LINUX";
// ELF note type definitions
-const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
+const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
const elf_word LLDB_NT_FREEBSD_ABI_SIZE = 4;
-const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
-const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
+const elf_word LLDB_NT_GNU_ABI_TAG = 0x01;
+const elf_word LLDB_NT_GNU_ABI_SIZE = 16;
const elf_word LLDB_NT_GNU_BUILD_ID_TAG = 0x03;
-const elf_word LLDB_NT_NETBSD_ABI_TAG = 0x01;
-const elf_word LLDB_NT_NETBSD_ABI_SIZE = 4;
+const elf_word LLDB_NT_NETBSD_ABI_TAG = 0x01;
+const elf_word LLDB_NT_NETBSD_ABI_SIZE = 4;
// GNU ABI note OS constants
-const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
-const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
+const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
+const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants
-#define NT_PRSTATUS 1
-#define NT_PRFPREG 2
-#define NT_PRPSINFO 3
-#define NT_TASKSTRUCT 4
-#define NT_AUXV 6
-#define NT_SIGINFO 0x53494749
-#define NT_FILE 0x46494c45
-#define NT_PRXFPREG 0x46e62b7f
-#define NT_PPC_VMX 0x100
-#define NT_PPC_SPE 0x101
-#define NT_PPC_VSX 0x102
-#define NT_386_TLS 0x200
-#define NT_386_IOPERM 0x201
-#define NT_X86_XSTATE 0x202
-#define NT_S390_HIGH_GPRS 0x300
-#define NT_S390_TIMER 0x301
-#define NT_S390_TODCMP 0x302
-#define NT_S390_TODPREG 0x303
-#define NT_S390_CTRS 0x304
-#define NT_S390_PREFIX 0x305
-#define NT_S390_LAST_BREAK 0x306
-#define NT_S390_SYSTEM_CALL 0x307
-#define NT_S390_TDB 0x308
-#define NT_S390_VXRS_LOW 0x309
-#define NT_S390_VXRS_HIGH 0x30a
-#define NT_ARM_VFP 0x400
-#define NT_ARM_TLS 0x401
-#define NT_ARM_HW_BREAK 0x402
-#define NT_ARM_HW_WATCH 0x403
-#define NT_ARM_SYSTEM_CALL 0x404
-#define NT_METAG_CBUF 0x500
-#define NT_METAG_RPIPE 0x501
-#define NT_METAG_TLS 0x502
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+#define NT_AUXV 6
+#define NT_SIGINFO 0x53494749
+#define NT_FILE 0x46494c45
+#define NT_PRXFPREG 0x46e62b7f
+#define NT_PPC_VMX 0x100
+#define NT_PPC_SPE 0x101
+#define NT_PPC_VSX 0x102
+#define NT_386_TLS 0x200
+#define NT_386_IOPERM 0x201
+#define NT_X86_XSTATE 0x202
+#define NT_S390_HIGH_GPRS 0x300
+#define NT_S390_TIMER 0x301
+#define NT_S390_TODCMP 0x302
+#define NT_S390_TODPREG 0x303
+#define NT_S390_CTRS 0x304
+#define NT_S390_PREFIX 0x305
+#define NT_S390_LAST_BREAK 0x306
+#define NT_S390_SYSTEM_CALL 0x307
+#define NT_S390_TDB 0x308
+#define NT_S390_VXRS_LOW 0x309
+#define NT_S390_VXRS_HIGH 0x30a
+#define NT_ARM_VFP 0x400
+#define NT_ARM_TLS 0x401
+#define NT_ARM_HW_BREAK 0x402
+#define NT_ARM_HW_WATCH 0x403
+#define NT_ARM_SYSTEM_CALL 0x404
+#define NT_METAG_CBUF 0x500
+#define NT_METAG_RPIPE 0x501
+#define NT_METAG_TLS 0x502
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
@@ -112,401 +114,335 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARI
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
-class ELFRelocation
-{
+class ELFRelocation {
public:
+ /// Constructs an ELFRelocation entry with a personality as given by @p
+ /// type.
+ ///
+ /// @param type Either DT_REL or DT_RELA. Any other value is invalid.
+ ELFRelocation(unsigned type);
- /// Constructs an ELFRelocation entry with a personality as given by @p
- /// type.
- ///
- /// @param type Either DT_REL or DT_RELA. Any other value is invalid.
- ELFRelocation(unsigned type);
+ ~ELFRelocation();
- ~ELFRelocation();
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+ static unsigned RelocType32(const ELFRelocation &rel);
- static unsigned
- RelocType32(const ELFRelocation &rel);
+ static unsigned RelocType64(const ELFRelocation &rel);
- static unsigned
- RelocType64(const ELFRelocation &rel);
+ static unsigned RelocSymbol32(const ELFRelocation &rel);
- static unsigned
- RelocSymbol32(const ELFRelocation &rel);
+ static unsigned RelocSymbol64(const ELFRelocation &rel);
- static unsigned
- RelocSymbol64(const ELFRelocation &rel);
+ static unsigned RelocOffset32(const ELFRelocation &rel);
- static unsigned
- RelocOffset32(const ELFRelocation &rel);
+ static unsigned RelocOffset64(const ELFRelocation &rel);
- static unsigned
- RelocOffset64(const ELFRelocation &rel);
+ static unsigned RelocAddend32(const ELFRelocation &rel);
- static unsigned
- RelocAddend32(const ELFRelocation &rel);
-
- static unsigned
- RelocAddend64(const ELFRelocation &rel);
+ static unsigned RelocAddend64(const ELFRelocation &rel);
private:
- typedef llvm::PointerUnion<ELFRel*, ELFRela*> RelocUnion;
+ typedef llvm::PointerUnion<ELFRel *, ELFRela *> RelocUnion;
- RelocUnion reloc;
+ RelocUnion reloc;
};
-ELFRelocation::ELFRelocation(unsigned type)
-{
- if (type == DT_REL || type == SHT_REL)
- reloc = new ELFRel();
- else if (type == DT_RELA || type == SHT_RELA)
- reloc = new ELFRela();
- else {
- assert(false && "unexpected relocation type");
- reloc = static_cast<ELFRel*>(NULL);
- }
+ELFRelocation::ELFRelocation(unsigned type) {
+ if (type == DT_REL || type == SHT_REL)
+ reloc = new ELFRel();
+ else if (type == DT_RELA || type == SHT_RELA)
+ reloc = new ELFRela();
+ else {
+ assert(false && "unexpected relocation type");
+ reloc = static_cast<ELFRel *>(NULL);
+ }
}
-ELFRelocation::~ELFRelocation()
-{
- if (reloc.is<ELFRel*>())
- delete reloc.get<ELFRel*>();
- else
- delete reloc.get<ELFRela*>();
+ELFRelocation::~ELFRelocation() {
+ if (reloc.is<ELFRel *>())
+ delete reloc.get<ELFRel *>();
+ else
+ delete reloc.get<ELFRela *>();
}
-bool
-ELFRelocation::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
-{
- if (reloc.is<ELFRel*>())
- return reloc.get<ELFRel*>()->Parse(data, offset);
- else
- return reloc.get<ELFRela*>()->Parse(data, offset);
+bool ELFRelocation::Parse(const lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ if (reloc.is<ELFRel *>())
+ return reloc.get<ELFRel *>()->Parse(data, offset);
+ else
+ return reloc.get<ELFRela *>()->Parse(data, offset);
}
-unsigned
-ELFRelocation::RelocType32(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return ELFRel::RelocType32(*rel.reloc.get<ELFRel*>());
- else
- return ELFRela::RelocType32(*rel.reloc.get<ELFRela*>());
+unsigned ELFRelocation::RelocType32(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return ELFRel::RelocType32(*rel.reloc.get<ELFRel *>());
+ else
+ return ELFRela::RelocType32(*rel.reloc.get<ELFRela *>());
}
-unsigned
-ELFRelocation::RelocType64(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return ELFRel::RelocType64(*rel.reloc.get<ELFRel*>());
- else
- return ELFRela::RelocType64(*rel.reloc.get<ELFRela*>());
+unsigned ELFRelocation::RelocType64(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return ELFRel::RelocType64(*rel.reloc.get<ELFRel *>());
+ else
+ return ELFRela::RelocType64(*rel.reloc.get<ELFRela *>());
}
-unsigned
-ELFRelocation::RelocSymbol32(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return ELFRel::RelocSymbol32(*rel.reloc.get<ELFRel*>());
- else
- return ELFRela::RelocSymbol32(*rel.reloc.get<ELFRela*>());
+unsigned ELFRelocation::RelocSymbol32(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return ELFRel::RelocSymbol32(*rel.reloc.get<ELFRel *>());
+ else
+ return ELFRela::RelocSymbol32(*rel.reloc.get<ELFRela *>());
}
-unsigned
-ELFRelocation::RelocSymbol64(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return ELFRel::RelocSymbol64(*rel.reloc.get<ELFRel*>());
- else
- return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela*>());
+unsigned ELFRelocation::RelocSymbol64(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return ELFRel::RelocSymbol64(*rel.reloc.get<ELFRel *>());
+ else
+ return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela *>());
}
-unsigned
-ELFRelocation::RelocOffset32(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return rel.reloc.get<ELFRel*>()->r_offset;
- else
- return rel.reloc.get<ELFRela*>()->r_offset;
+unsigned ELFRelocation::RelocOffset32(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return rel.reloc.get<ELFRel *>()->r_offset;
+ else
+ return rel.reloc.get<ELFRela *>()->r_offset;
}
-unsigned
-ELFRelocation::RelocOffset64(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return rel.reloc.get<ELFRel*>()->r_offset;
- else
- return rel.reloc.get<ELFRela*>()->r_offset;
+unsigned ELFRelocation::RelocOffset64(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return rel.reloc.get<ELFRel *>()->r_offset;
+ else
+ return rel.reloc.get<ELFRela *>()->r_offset;
}
-unsigned
-ELFRelocation::RelocAddend32(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return 0;
- else
- return rel.reloc.get<ELFRela*>()->r_addend;
+unsigned ELFRelocation::RelocAddend32(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return 0;
+ else
+ return rel.reloc.get<ELFRela *>()->r_addend;
}
-unsigned
-ELFRelocation::RelocAddend64(const ELFRelocation &rel)
-{
- if (rel.reloc.is<ELFRel*>())
- return 0;
- else
- return rel.reloc.get<ELFRela*>()->r_addend;
+unsigned ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
+ if (rel.reloc.is<ELFRel *>())
+ return 0;
+ else
+ return rel.reloc.get<ELFRela *>()->r_addend;
}
} // end anonymous namespace
-bool
-ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset)
-{
- // Read all fields.
- if (data.GetU32(offset, &n_namesz, 3) == NULL)
- return false;
-
- // The name field is required to be nul-terminated, and n_namesz
- // includes the terminating nul in observed implementations (contrary
- // to the ELF-64 spec). A special case is needed for cores generated
- // by some older Linux versions, which write a note named "CORE"
- // without a nul terminator and n_namesz = 4.
- if (n_namesz == 4)
- {
- char buf[4];
- if (data.ExtractBytes (*offset, 4, data.GetByteOrder(), buf) != 4)
- return false;
- if (strncmp (buf, "CORE", 4) == 0)
- {
- n_name = "CORE";
- *offset += 4;
- return true;
- }
- }
-
- const char *cstr = data.GetCStr(offset, llvm::alignTo (n_namesz, 4));
- if (cstr == NULL)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
- if (log)
- log->Printf("Failed to parse note name lacking nul terminator");
-
- return false;
- }
- n_name = cstr;
- return true;
-}
-
-static uint32_t
-kalimbaVariantFromElfFlags(const elf::elf_word e_flags)
-{
- const uint32_t dsp_rev = e_flags & 0xFF;
- uint32_t kal_arch_variant = LLDB_INVALID_CPUTYPE;
- switch(dsp_rev)
- {
- // TODO(mg11) Support more variants
- case 10:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v3;
- break;
- case 14:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v4;
- break;
- case 17:
- case 20:
- kal_arch_variant = llvm::Triple::KalimbaSubArch_v5;
- break;
- default:
- break;
- }
- return kal_arch_variant;
-}
-
-static uint32_t
-mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian)
-{
- const uint32_t mips_arch = e_flags & llvm::ELF::EF_MIPS_ARCH;
- uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
-
- switch (mips_arch)
- {
- case llvm::ELF::EF_MIPS_ARCH_1:
- case llvm::ELF::EF_MIPS_ARCH_2:
- case llvm::ELF::EF_MIPS_ARCH_32:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32;
- case llvm::ELF::EF_MIPS_ARCH_32R2:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el : ArchSpec::eMIPSSubType_mips32r2;
- case llvm::ELF::EF_MIPS_ARCH_32R6:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el : ArchSpec::eMIPSSubType_mips32r6;
- case llvm::ELF::EF_MIPS_ARCH_3:
- case llvm::ELF::EF_MIPS_ARCH_4:
- case llvm::ELF::EF_MIPS_ARCH_5:
- case llvm::ELF::EF_MIPS_ARCH_64:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el : ArchSpec::eMIPSSubType_mips64;
- case llvm::ELF::EF_MIPS_ARCH_64R2:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r2el : ArchSpec::eMIPSSubType_mips64r2;
- case llvm::ELF::EF_MIPS_ARCH_64R6:
- return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r6el : ArchSpec::eMIPSSubType_mips64r6;
- default:
- break;
- }
+bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
+ // Read all fields.
+ if (data.GetU32(offset, &n_namesz, 3) == NULL)
+ return false;
- return arch_variant;
-}
+ // The name field is required to be nul-terminated, and n_namesz
+ // includes the terminating nul in observed implementations (contrary
+ // to the ELF-64 spec). A special case is needed for cores generated
+ // by some older Linux versions, which write a note named "CORE"
+ // without a nul terminator and n_namesz = 4.
+ if (n_namesz == 4) {
+ char buf[4];
+ if (data.ExtractBytes(*offset, 4, data.GetByteOrder(), buf) != 4)
+ return false;
+ if (strncmp(buf, "CORE", 4) == 0) {
+ n_name = "CORE";
+ *offset += 4;
+ return true;
+ }
+ }
+
+ const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4));
+ if (cstr == NULL) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));
+ if (log)
+ log->Printf("Failed to parse note name lacking nul terminator");
-static uint32_t
-subTypeFromElfHeader(const elf::ELFHeader& header)
-{
- if (header.e_machine == llvm::ELF::EM_MIPS)
- return mipsVariantFromElfFlags (header.e_flags,
- header.e_ident[EI_DATA]);
-
- return
- llvm::ELF::EM_CSR_KALIMBA == header.e_machine ?
- kalimbaVariantFromElfFlags(header.e_flags) :
- LLDB_INVALID_CPUTYPE;
+ return false;
+ }
+ n_name = cstr;
+ return true;
+}
+
+static uint32_t kalimbaVariantFromElfFlags(const elf::elf_word e_flags) {
+ const uint32_t dsp_rev = e_flags & 0xFF;
+ uint32_t kal_arch_variant = LLDB_INVALID_CPUTYPE;
+ switch (dsp_rev) {
+ // TODO(mg11) Support more variants
+ case 10:
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v3;
+ break;
+ case 14:
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v4;
+ break;
+ case 17:
+ case 20:
+ kal_arch_variant = llvm::Triple::KalimbaSubArch_v5;
+ break;
+ default:
+ break;
+ }
+ return kal_arch_variant;
+}
+
+static uint32_t mipsVariantFromElfFlags(const elf::elf_word e_flags,
+ uint32_t endian) {
+ const uint32_t mips_arch = e_flags & llvm::ELF::EF_MIPS_ARCH;
+ uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
+
+ switch (mips_arch) {
+ case llvm::ELF::EF_MIPS_ARCH_1:
+ case llvm::ELF::EF_MIPS_ARCH_2:
+ case llvm::ELF::EF_MIPS_ARCH_32:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el
+ : ArchSpec::eMIPSSubType_mips32;
+ case llvm::ELF::EF_MIPS_ARCH_32R2:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el
+ : ArchSpec::eMIPSSubType_mips32r2;
+ case llvm::ELF::EF_MIPS_ARCH_32R6:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el
+ : ArchSpec::eMIPSSubType_mips32r6;
+ case llvm::ELF::EF_MIPS_ARCH_3:
+ case llvm::ELF::EF_MIPS_ARCH_4:
+ case llvm::ELF::EF_MIPS_ARCH_5:
+ case llvm::ELF::EF_MIPS_ARCH_64:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el
+ : ArchSpec::eMIPSSubType_mips64;
+ case llvm::ELF::EF_MIPS_ARCH_64R2:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r2el
+ : ArchSpec::eMIPSSubType_mips64r2;
+ case llvm::ELF::EF_MIPS_ARCH_64R6:
+ return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r6el
+ : ArchSpec::eMIPSSubType_mips64r6;
+ default:
+ break;
+ }
+
+ return arch_variant;
+}
+
+static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) {
+ if (header.e_machine == llvm::ELF::EM_MIPS)
+ return mipsVariantFromElfFlags(header.e_flags, header.e_ident[EI_DATA]);
+
+ return llvm::ELF::EM_CSR_KALIMBA == header.e_machine
+ ? kalimbaVariantFromElfFlags(header.e_flags)
+ : LLDB_INVALID_CPUTYPE;
}
//! The kalimba toolchain identifies a code section as being
//! one with the SHT_PROGBITS set in the section sh_type and the top
//! bit in the 32-bit address field set.
static lldb::SectionType
-kalimbaSectionType(
- const elf::ELFHeader& header,
- const elf::ELFSectionHeader& sect_hdr)
-{
- if (llvm::ELF::EM_CSR_KALIMBA != header.e_machine)
- {
- return eSectionTypeOther;
- }
-
- if (llvm::ELF::SHT_NOBITS == sect_hdr.sh_type)
- {
- return eSectionTypeZeroFill;
- }
-
- if (llvm::ELF::SHT_PROGBITS == sect_hdr.sh_type)
- {
- const lldb::addr_t KAL_CODE_BIT = 1 << 31;
- return KAL_CODE_BIT & sect_hdr.sh_addr ?
- eSectionTypeCode : eSectionTypeData;
- }
-
+kalimbaSectionType(const elf::ELFHeader &header,
+ const elf::ELFSectionHeader §_hdr) {
+ if (llvm::ELF::EM_CSR_KALIMBA != header.e_machine) {
return eSectionTypeOther;
+ }
+
+ if (llvm::ELF::SHT_NOBITS == sect_hdr.sh_type) {
+ return eSectionTypeZeroFill;
+ }
+
+ if (llvm::ELF::SHT_PROGBITS == sect_hdr.sh_type) {
+ const lldb::addr_t KAL_CODE_BIT = 1 << 31;
+ return KAL_CODE_BIT & sect_hdr.sh_addr ? eSectionTypeCode
+ : eSectionTypeData;
+ }
+
+ return eSectionTypeOther;
}
// Arbitrary constant used as UUID prefix for core files.
-const uint32_t
-ObjectFileELF::g_core_uuid_magic(0xE210C);
+const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C);
//------------------------------------------------------------------
// Static methods.
//------------------------------------------------------------------
-void
-ObjectFileELF::Initialize()
-{
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- CreateMemoryInstance,
- GetModuleSpecifications);
-}
-
-void
-ObjectFileELF::Terminate()
-{
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString
-ObjectFileELF::GetPluginNameStatic()
-{
- static ConstString g_name("elf");
- return g_name;
-}
-
-const char *
-ObjectFileELF::GetPluginDescriptionStatic()
-{
- return "ELF object file reader.";
-}
-
-ObjectFile *
-ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP &data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec* file,
- lldb::offset_t file_offset,
- lldb::offset_t length)
-{
- if (!data_sp)
- {
+void ObjectFileELF::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFileELF::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString ObjectFileELF::GetPluginNameStatic() {
+ static ConstString g_name("elf");
+ return g_name;
+}
+
+const char *ObjectFileELF::GetPluginDescriptionStatic() {
+ return "ELF object file reader.";
+}
+
+ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
+ DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec *file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length) {
+ if (!data_sp) {
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
+ data_offset = 0;
+ }
+
+ if (data_sp &&
+ data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset)) {
+ const uint8_t *magic = data_sp->GetBytes() + data_offset;
+ if (ELFHeader::MagicBytesMatch(magic)) {
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length) {
data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
- }
-
- if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
- {
- const uint8_t *magic = data_sp->GetBytes() + data_offset;
- if (ELFHeader::MagicBytesMatch(magic))
- {
- // Update the data to contain the entire file if it doesn't already
- if (data_sp->GetByteSize() < length) {
- data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
- data_offset = 0;
- magic = data_sp->GetBytes();
- }
- unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
- if (address_size == 4 || address_size == 8)
- {
- std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, data_offset, file, file_offset, length));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
- return objfile_ap.release();
- }
- }
- }
- return NULL;
-}
-
-
-ObjectFile*
-ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- const lldb::ProcessSP &process_sp,
- lldb::addr_t header_addr)
-{
- if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT))
- {
- const uint8_t *magic = data_sp->GetBytes();
- if (ELFHeader::MagicBytesMatch(magic))
- {
- unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
- if (address_size == 4 || address_size == 8)
- {
- std::auto_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
- return objfile_ap.release();
- }
- }
- }
- return NULL;
-}
-
-bool
-ObjectFileELF::MagicBytesMatch (DataBufferSP& data_sp,
- lldb::addr_t data_offset,
- lldb::addr_t data_length)
-{
- if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
- {
- const uint8_t *magic = data_sp->GetBytes() + data_offset;
- return ELFHeader::MagicBytesMatch(magic);
- }
- return false;
+ magic = data_sp->GetBytes();
+ }
+ unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
+ if (address_size == 4 || address_size == 8) {
+ std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(
+ module_sp, data_sp, data_offset, file, file_offset, length));
+ ArchSpec spec;
+ if (objfile_ap->GetArchitecture(spec) &&
+ objfile_ap->SetModulesArchitecture(spec))
+ return objfile_ap.release();
+ }
+ }
+ }
+ return NULL;
+}
+
+ObjectFile *ObjectFileELF::CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
+ if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT)) {
+ const uint8_t *magic = data_sp->GetBytes();
+ if (ELFHeader::MagicBytesMatch(magic)) {
+ unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
+ if (address_size == 4 || address_size == 8) {
+ std::auto_ptr<ObjectFileELF> objfile_ap(
+ new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
+ ArchSpec spec;
+ if (objfile_ap->GetArchitecture(spec) &&
+ objfile_ap->SetModulesArchitecture(spec))
+ return objfile_ap.release();
+ }
+ }
+ }
+ return NULL;
+}
+
+bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp,
+ lldb::addr_t data_offset,
+ lldb::addr_t data_length) {
+ if (data_sp &&
+ data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset)) {
+ const uint8_t *magic = data_sp->GetBytes() + data_offset;
+ return ELFHeader::MagicBytesMatch(magic);
+ }
+ return false;
}
/*
@@ -515,130 +451,117 @@ ObjectFileELF::MagicBytesMatch (DataBuff
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*/
-static uint32_t
-calc_crc32(uint32_t crc, const void *buf, size_t size)
-{
- static const uint32_t g_crc32_tab[] =
- {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
- };
- const uint8_t *p = (const uint8_t *)buf;
-
- crc = crc ^ ~0U;
- while (size--)
- crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
- return crc ^ ~0U;
-}
-
-static uint32_t
-calc_gnu_debuglink_crc32(const void *buf, size_t size)
-{
- return calc_crc32(0U, buf, size);
-}
-
-uint32_t
-ObjectFileELF::CalculateELFNotesSegmentsCRC32 (const ProgramHeaderColl& program_headers,
- DataExtractor& object_data)
-{
- typedef ProgramHeaderCollConstIter Iter;
-
- uint32_t core_notes_crc = 0;
-
- for (Iter I = program_headers.begin(); I != program_headers.end(); ++I)
- {
- if (I->p_type == llvm::ELF::PT_NOTE)
- {
- const elf_off ph_offset = I->p_offset;
- const size_t ph_size = I->p_filesz;
-
- DataExtractor segment_data;
- if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size)
- {
- // The ELF program header contained incorrect data,
- // probably corefile is incomplete or corrupted.
- break;
- }
+static uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size) {
+ static const uint32_t g_crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
+ const uint8_t *p = (const uint8_t *)buf;
+
+ crc = crc ^ ~0U;
+ while (size--)
+ crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+ return crc ^ ~0U;
+}
+
+static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) {
+ return calc_crc32(0U, buf, size);
+}
+
+uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
+ const ProgramHeaderColl &program_headers, DataExtractor &object_data) {
+ typedef ProgramHeaderCollConstIter Iter;
+
+ uint32_t core_notes_crc = 0;
+
+ for (Iter I = program_headers.begin(); I != program_headers.end(); ++I) {
+ if (I->p_type == llvm::ELF::PT_NOTE) {
+ const elf_off ph_offset = I->p_offset;
+ const size_t ph_size = I->p_filesz;
+
+ DataExtractor segment_data;
+ if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
+ // The ELF program header contained incorrect data,
+ // probably corefile is incomplete or corrupted.
+ break;
+ }
- core_notes_crc = calc_crc32(core_notes_crc,
- segment_data.GetDataStart(),
- segment_data.GetByteSize());
- }
+ core_notes_crc = calc_crc32(core_notes_crc, segment_data.GetDataStart(),
+ segment_data.GetByteSize());
}
+ }
- return core_notes_crc;
-}
-
-static const char*
-OSABIAsCString (unsigned char osabi_byte)
-{
-#define _MAKE_OSABI_CASE(x) case x: return #x
- switch (osabi_byte)
- {
- _MAKE_OSABI_CASE(ELFOSABI_NONE);
- _MAKE_OSABI_CASE(ELFOSABI_HPUX);
- _MAKE_OSABI_CASE(ELFOSABI_NETBSD);
- _MAKE_OSABI_CASE(ELFOSABI_GNU);
- _MAKE_OSABI_CASE(ELFOSABI_HURD);
- _MAKE_OSABI_CASE(ELFOSABI_SOLARIS);
- _MAKE_OSABI_CASE(ELFOSABI_AIX);
- _MAKE_OSABI_CASE(ELFOSABI_IRIX);
- _MAKE_OSABI_CASE(ELFOSABI_FREEBSD);
- _MAKE_OSABI_CASE(ELFOSABI_TRU64);
- _MAKE_OSABI_CASE(ELFOSABI_MODESTO);
- _MAKE_OSABI_CASE(ELFOSABI_OPENBSD);
- _MAKE_OSABI_CASE(ELFOSABI_OPENVMS);
- _MAKE_OSABI_CASE(ELFOSABI_NSK);
- _MAKE_OSABI_CASE(ELFOSABI_AROS);
- _MAKE_OSABI_CASE(ELFOSABI_FENIXOS);
- _MAKE_OSABI_CASE(ELFOSABI_C6000_ELFABI);
- _MAKE_OSABI_CASE(ELFOSABI_C6000_LINUX);
- _MAKE_OSABI_CASE(ELFOSABI_ARM);
- _MAKE_OSABI_CASE(ELFOSABI_STANDALONE);
- default:
- return "<unknown-osabi>";
- }
+ return core_notes_crc;
+}
+
+static const char *OSABIAsCString(unsigned char osabi_byte) {
+#define _MAKE_OSABI_CASE(x) \
+ case x: \
+ return #x
+ switch (osabi_byte) {
+ _MAKE_OSABI_CASE(ELFOSABI_NONE);
+ _MAKE_OSABI_CASE(ELFOSABI_HPUX);
+ _MAKE_OSABI_CASE(ELFOSABI_NETBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_GNU);
+ _MAKE_OSABI_CASE(ELFOSABI_HURD);
+ _MAKE_OSABI_CASE(ELFOSABI_SOLARIS);
+ _MAKE_OSABI_CASE(ELFOSABI_AIX);
+ _MAKE_OSABI_CASE(ELFOSABI_IRIX);
+ _MAKE_OSABI_CASE(ELFOSABI_FREEBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_TRU64);
+ _MAKE_OSABI_CASE(ELFOSABI_MODESTO);
+ _MAKE_OSABI_CASE(ELFOSABI_OPENBSD);
+ _MAKE_OSABI_CASE(ELFOSABI_OPENVMS);
+ _MAKE_OSABI_CASE(ELFOSABI_NSK);
+ _MAKE_OSABI_CASE(ELFOSABI_AROS);
+ _MAKE_OSABI_CASE(ELFOSABI_FENIXOS);
+ _MAKE_OSABI_CASE(ELFOSABI_C6000_ELFABI);
+ _MAKE_OSABI_CASE(ELFOSABI_C6000_LINUX);
+ _MAKE_OSABI_CASE(ELFOSABI_ARM);
+ _MAKE_OSABI_CASE(ELFOSABI_STANDALONE);
+ default:
+ return "<unknown-osabi>";
+ }
#undef _MAKE_OSABI_CASE
}
@@ -648,2492 +571,2422 @@ OSABIAsCString (unsigned char osabi_byte
// This function is only being kept to validate the move.
//
// TODO : Remove this function
-static bool
-GetOsFromOSABI (unsigned char osabi_byte, llvm::Triple::OSType &ostype)
-{
- switch (osabi_byte)
- {
- case ELFOSABI_AIX: ostype = llvm::Triple::OSType::AIX; break;
- case ELFOSABI_FREEBSD: ostype = llvm::Triple::OSType::FreeBSD; break;
- case ELFOSABI_GNU: ostype = llvm::Triple::OSType::Linux; break;
- case ELFOSABI_NETBSD: ostype = llvm::Triple::OSType::NetBSD; break;
- case ELFOSABI_OPENBSD: ostype = llvm::Triple::OSType::OpenBSD; break;
- case ELFOSABI_SOLARIS: ostype = llvm::Triple::OSType::Solaris; break;
- default:
- ostype = llvm::Triple::OSType::UnknownOS;
- }
- return ostype != llvm::Triple::OSType::UnknownOS;
-}
-
-size_t
-ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
-
- const size_t initial_count = specs.GetSize();
-
- if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
- {
- DataExtractor data;
- data.SetData(data_sp);
- elf::ELFHeader header;
- if (header.Parse(data, &data_offset))
- {
- if (data_sp)
- {
- ModuleSpec spec (file);
-
- const uint32_t sub_type = subTypeFromElfHeader(header);
- spec.GetArchitecture().SetArchitecture(eArchTypeELF,
- header.e_machine,
- sub_type,
- header.e_ident[EI_OSABI]);
-
- if (spec.GetArchitecture().IsValid())
- {
- llvm::Triple::OSType ostype;
- llvm::Triple::VendorType vendor;
- llvm::Triple::OSType spec_ostype = spec.GetArchitecture ().GetTriple ().getOS ();
-
- if (log)
- log->Printf ("ObjectFileELF::%s file '%s' module OSABI: %s", __FUNCTION__, file.GetPath ().c_str (), OSABIAsCString (header.e_ident[EI_OSABI]));
-
- // SetArchitecture should have set the vendor to unknown
- vendor = spec.GetArchitecture ().GetTriple ().getVendor ();
- assert(vendor == llvm::Triple::UnknownVendor);
-
- //
- // Validate it is ok to remove GetOsFromOSABI
- GetOsFromOSABI (header.e_ident[EI_OSABI], ostype);
- assert(spec_ostype == ostype);
- if (spec_ostype != llvm::Triple::OSType::UnknownOS)
- {
- if (log)
- log->Printf ("ObjectFileELF::%s file '%s' set ELF module OS type from ELF header OSABI.", __FUNCTION__, file.GetPath ().c_str ());
- }
-
- // Try to get the UUID from the section list. Usually that's at the end, so
- // map the file in if we don't have it already.
- size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize;
- if (section_header_end > data_sp->GetByteSize())
- {
- data_sp = file.MemoryMapFileContentsIfLocal (file_offset, section_header_end);
- data.SetData(data_sp);
- }
-
- uint32_t gnu_debuglink_crc = 0;
- std::string gnu_debuglink_file;
- SectionHeaderColl section_headers;
- lldb_private::UUID &uuid = spec.GetUUID();
-
- using namespace std::placeholders;
- const SetDataFunction set_data = std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3);
- GetSectionHeaderInfo(section_headers, set_data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ());
-
-
- llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple ();
-
- if (log)
- log->Printf ("ObjectFileELF::%s file '%s' module set to triple: %s (architecture %s)", __FUNCTION__, file.GetPath ().c_str (), spec_triple.getTriple ().c_str (), spec.GetArchitecture ().GetArchitectureName ());
-
- if (!uuid.IsValid())
- {
- uint32_t core_notes_crc = 0;
-
- if (!gnu_debuglink_crc)
- {
- lldb_private::Timer scoped_timer (LLVM_PRETTY_FUNCTION,
- "Calculating module crc32 %s with size %" PRIu64 " KiB",
- file.GetLastPathComponent().AsCString(),
- (file.GetByteSize()-file_offset)/1024);
-
- // For core files - which usually don't happen to have a gnu_debuglink,
- // and are pretty bulky - calculating whole contents crc32 would be too much of luxury.
- // Thus we will need to fallback to something simpler.
- if (header.e_type == llvm::ELF::ET_CORE)
- {
- size_t program_headers_end = header.e_phoff + header.e_phnum * header.e_phentsize;
- if (program_headers_end > data_sp->GetByteSize())
- {
- data_sp = file.MemoryMapFileContentsIfLocal(file_offset, program_headers_end);
- data.SetData(data_sp);
- }
- ProgramHeaderColl program_headers;
- GetProgramHeaderInfo(program_headers, set_data, header);
-
- size_t segment_data_end = 0;
- for (ProgramHeaderCollConstIter I = program_headers.begin();
- I != program_headers.end(); ++I)
- {
- segment_data_end = std::max<unsigned long long> (I->p_offset + I->p_filesz, segment_data_end);
- }
-
- if (segment_data_end > data_sp->GetByteSize())
- {
- data_sp = file.MemoryMapFileContentsIfLocal(file_offset, segment_data_end);
- data.SetData(data_sp);
- }
-
- core_notes_crc = CalculateELFNotesSegmentsCRC32 (program_headers, data);
- }
- else
- {
- // Need to map entire file into memory to calculate the crc.
- data_sp = file.MemoryMapFileContentsIfLocal (file_offset, SIZE_MAX);
- data.SetData(data_sp);
- gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());
- }
- }
- if (gnu_debuglink_crc)
- {
- // Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = { gnu_debuglink_crc, 0, 0, 0 };
- uuid.SetBytes (uuidt, sizeof(uuidt));
- }
- else if (core_notes_crc)
- {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look different form
- // .gnu_debuglink crc followed by 4 bytes of note segments crc.
- uint32_t uuidt[4] = { g_core_uuid_magic, core_notes_crc, 0, 0 };
- uuid.SetBytes (uuidt, sizeof(uuidt));
- }
- }
+static bool GetOsFromOSABI(unsigned char osabi_byte,
+ llvm::Triple::OSType &ostype) {
+ switch (osabi_byte) {
+ case ELFOSABI_AIX:
+ ostype = llvm::Triple::OSType::AIX;
+ break;
+ case ELFOSABI_FREEBSD:
+ ostype = llvm::Triple::OSType::FreeBSD;
+ break;
+ case ELFOSABI_GNU:
+ ostype = llvm::Triple::OSType::Linux;
+ break;
+ case ELFOSABI_NETBSD:
+ ostype = llvm::Triple::OSType::NetBSD;
+ break;
+ case ELFOSABI_OPENBSD:
+ ostype = llvm::Triple::OSType::OpenBSD;
+ break;
+ case ELFOSABI_SOLARIS:
+ ostype = llvm::Triple::OSType::Solaris;
+ break;
+ default:
+ ostype = llvm::Triple::OSType::UnknownOS;
+ }
+ return ostype != llvm::Triple::OSType::UnknownOS;
+}
+
+size_t ObjectFileELF::GetModuleSpecifications(
+ const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, lldb::offset_t file_offset,
+ lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES));
- specs.Append(spec);
- }
- }
+ const size_t initial_count = specs.GetSize();
+
+ if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) {
+ DataExtractor data;
+ data.SetData(data_sp);
+ elf::ELFHeader header;
+ if (header.Parse(data, &data_offset)) {
+ if (data_sp) {
+ ModuleSpec spec(file);
+
+ const uint32_t sub_type = subTypeFromElfHeader(header);
+ spec.GetArchitecture().SetArchitecture(
+ eArchTypeELF, header.e_machine, sub_type, header.e_ident[EI_OSABI]);
+
+ if (spec.GetArchitecture().IsValid()) {
+ llvm::Triple::OSType ostype;
+ llvm::Triple::VendorType vendor;
+ llvm::Triple::OSType spec_ostype =
+ spec.GetArchitecture().GetTriple().getOS();
+
+ if (log)
+ log->Printf("ObjectFileELF::%s file '%s' module OSABI: %s",
+ __FUNCTION__, file.GetPath().c_str(),
+ OSABIAsCString(header.e_ident[EI_OSABI]));
+
+ // SetArchitecture should have set the vendor to unknown
+ vendor = spec.GetArchitecture().GetTriple().getVendor();
+ assert(vendor == llvm::Triple::UnknownVendor);
+
+ //
+ // Validate it is ok to remove GetOsFromOSABI
+ GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
+ assert(spec_ostype == ostype);
+ if (spec_ostype != llvm::Triple::OSType::UnknownOS) {
+ if (log)
+ log->Printf("ObjectFileELF::%s file '%s' set ELF module OS type "
+ "from ELF header OSABI.",
+ __FUNCTION__, file.GetPath().c_str());
+ }
+
+ // Try to get the UUID from the section list. Usually that's at the
+ // end, so
+ // map the file in if we don't have it already.
+ size_t section_header_end =
+ header.e_shoff + header.e_shnum * header.e_shentsize;
+ if (section_header_end > data_sp->GetByteSize()) {
+ data_sp = file.MemoryMapFileContentsIfLocal(file_offset,
+ section_header_end);
+ data.SetData(data_sp);
+ }
+
+ uint32_t gnu_debuglink_crc = 0;
+ std::string gnu_debuglink_file;
+ SectionHeaderColl section_headers;
+ lldb_private::UUID &uuid = spec.GetUUID();
+
+ using namespace std::placeholders;
+ const SetDataFunction set_data =
+ std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3);
+ GetSectionHeaderInfo(section_headers, set_data, header, uuid,
+ gnu_debuglink_file, gnu_debuglink_crc,
+ spec.GetArchitecture());
+
+ llvm::Triple &spec_triple = spec.GetArchitecture().GetTriple();
+
+ if (log)
+ log->Printf("ObjectFileELF::%s file '%s' module set to triple: %s "
+ "(architecture %s)",
+ __FUNCTION__, file.GetPath().c_str(),
+ spec_triple.getTriple().c_str(),
+ spec.GetArchitecture().GetArchitectureName());
+
+ if (!uuid.IsValid()) {
+ uint32_t core_notes_crc = 0;
+
+ if (!gnu_debuglink_crc) {
+ lldb_private::Timer scoped_timer(
+ LLVM_PRETTY_FUNCTION,
+ "Calculating module crc32 %s with size %" PRIu64 " KiB",
+ file.GetLastPathComponent().AsCString(),
+ (file.GetByteSize() - file_offset) / 1024);
+
+ // For core files - which usually don't happen to have a
+ // gnu_debuglink,
+ // and are pretty bulky - calculating whole contents crc32 would
+ // be too much of luxury.
+ // Thus we will need to fallback to something simpler.
+ if (header.e_type == llvm::ELF::ET_CORE) {
+ size_t program_headers_end =
+ header.e_phoff + header.e_phnum * header.e_phentsize;
+ if (program_headers_end > data_sp->GetByteSize()) {
+ data_sp = file.MemoryMapFileContentsIfLocal(
+ file_offset, program_headers_end);
+ data.SetData(data_sp);
+ }
+ ProgramHeaderColl program_headers;
+ GetProgramHeaderInfo(program_headers, set_data, header);
+
+ size_t segment_data_end = 0;
+ for (ProgramHeaderCollConstIter I = program_headers.begin();
+ I != program_headers.end(); ++I) {
+ segment_data_end = std::max<unsigned long long>(
+ I->p_offset + I->p_filesz, segment_data_end);
+ }
+
+ if (segment_data_end > data_sp->GetByteSize()) {
+ data_sp = file.MemoryMapFileContentsIfLocal(file_offset,
+ segment_data_end);
+ data.SetData(data_sp);
+ }
+
+ core_notes_crc =
+ CalculateELFNotesSegmentsCRC32(program_headers, data);
+ } else {
+ // Need to map entire file into memory to calculate the crc.
+ data_sp =
+ file.MemoryMapFileContentsIfLocal(file_offset, SIZE_MAX);
+ data.SetData(data_sp);
+ gnu_debuglink_crc = calc_gnu_debuglink_crc32(
+ data.GetDataStart(), data.GetByteSize());
+ }
+ }
+ if (gnu_debuglink_crc) {
+ // Use 4 bytes of crc from the .gnu_debuglink section.
+ uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0};
+ uuid.SetBytes(uuidt, sizeof(uuidt));
+ } else if (core_notes_crc) {
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make
+ // it look different form
+ // .gnu_debuglink crc followed by 4 bytes of note segments crc.
+ uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
+ uuid.SetBytes(uuidt, sizeof(uuidt));
+ }
+ }
+
+ specs.Append(spec);
}
+ }
}
+ }
- return specs.GetSize() - initial_count;
+ return specs.GetSize() - initial_count;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-ObjectFileELF::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString ObjectFileELF::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-ObjectFileELF::GetPluginVersion()
-{
- return m_plugin_version;
-}
+uint32_t ObjectFileELF::GetPluginVersion() { return m_plugin_version; }
//------------------------------------------------------------------
// ObjectFile protocol
//------------------------------------------------------------------
-ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const FileSpec* file,
- lldb::offset_t file_offset,
- lldb::offset_t length) :
- ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
- m_header(),
- m_uuid(),
- m_gnu_debuglink_file(),
- m_gnu_debuglink_crc(0),
- m_program_headers(),
- m_section_headers(),
- m_dynamic_symbols(),
- m_filespec_ap(),
- m_entry_point_address(),
- m_arch_spec()
-{
- if (file)
- m_file = *file;
- ::memset(&m_header, 0, sizeof(m_header));
-}
-
-ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,
- DataBufferSP& header_data_sp,
- const lldb::ProcessSP &process_sp,
- addr_t header_addr) :
- ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
- m_header(),
- m_uuid(),
- m_gnu_debuglink_file(),
- m_gnu_debuglink_crc(0),
- m_program_headers(),
- m_section_headers(),
- m_dynamic_symbols(),
- m_filespec_ap(),
- m_entry_point_address(),
- m_arch_spec()
-{
- ::memset(&m_header, 0, sizeof(m_header));
-}
-
-ObjectFileELF::~ObjectFileELF()
-{
-}
-
-bool
-ObjectFileELF::IsExecutable() const
-{
- return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0);
-}
-
-bool
-ObjectFileELF::SetLoadAddress (Target &target,
- lldb::addr_t value,
- bool value_is_offset)
-{
- ModuleSP module_sp = GetModule();
- if (module_sp)
- {
- size_t num_loaded_sections = 0;
- SectionList *section_list = GetSectionList ();
- if (section_list)
- {
- if (!value_is_offset)
- {
- bool found_offset = false;
- for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
- {
- const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
- if (header == nullptr)
- continue;
-
- if (header->p_type != PT_LOAD || header->p_offset != 0)
- continue;
-
- value = value - header->p_vaddr;
- found_offset = true;
- break;
- }
- if (!found_offset)
- return false;
- }
+ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
+ DataBufferSP &data_sp, lldb::offset_t data_offset,
+ const FileSpec *file, lldb::offset_t file_offset,
+ lldb::offset_t length)
+ : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
+ m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0),
+ m_program_headers(), m_section_headers(), m_dynamic_symbols(),
+ m_filespec_ap(), m_entry_point_address(), m_arch_spec() {
+ if (file)
+ m_file = *file;
+ ::memset(&m_header, 0, sizeof(m_header));
+}
+
+ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,
+ DataBufferSP &header_data_sp,
+ const lldb::ProcessSP &process_sp,
+ addr_t header_addr)
+ : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
+ m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0),
+ m_program_headers(), m_section_headers(), m_dynamic_symbols(),
+ m_filespec_ap(), m_entry_point_address(), m_arch_spec() {
+ ::memset(&m_header, 0, sizeof(m_header));
+}
+
+ObjectFileELF::~ObjectFileELF() {}
+
+bool ObjectFileELF::IsExecutable() const {
+ return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0);
+}
+
+bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
+ bool value_is_offset) {
+ ModuleSP module_sp = GetModule();
+ if (module_sp) {
+ size_t num_loaded_sections = 0;
+ SectionList *section_list = GetSectionList();
+ if (section_list) {
+ if (!value_is_offset) {
+ bool found_offset = false;
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) {
+ const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
+ if (header == nullptr)
+ continue;
- const size_t num_sections = section_list->GetSize();
- size_t sect_idx = 0;
+ if (header->p_type != PT_LOAD || header->p_offset != 0)
+ continue;
- for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
- {
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
- SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
- if (section_sp && section_sp->Test(SHF_ALLOC))
- {
- lldb::addr_t load_addr = section_sp->GetFileAddress();
- // We don't want to update the load address of a section with type
- // eSectionTypeAbsoluteAddress as they already have the absolute load address
- // already specified
- if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
- load_addr += value;
-
- // On 32-bit systems the load address have to fit into 4 bytes. The rest of
- // the bytes are the overflow from the addition.
- if (GetAddressByteSize() == 4)
- load_addr &= 0xFFFFFFFF;
+ value = value - header->p_vaddr;
+ found_offset = true;
+ break;
+ }
+ if (!found_offset)
+ return false;
+ }
- if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
- ++num_loaded_sections;
- }
- }
- return num_loaded_sections > 0;
+ const size_t num_sections = section_list->GetSize();
+ size_t sect_idx = 0;
+
+ for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+ // Iterate through the object file sections to find all
+ // of the sections that have SHF_ALLOC in their flag bits.
+ SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
+ if (section_sp && section_sp->Test(SHF_ALLOC)) {
+ lldb::addr_t load_addr = section_sp->GetFileAddress();
+ // We don't want to update the load address of a section with type
+ // eSectionTypeAbsoluteAddress as they already have the absolute load
+ // address
+ // already specified
+ if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
+ load_addr += value;
+
+ // On 32-bit systems the load address have to fit into 4 bytes. The
+ // rest of
+ // the bytes are the overflow from the addition.
+ if (GetAddressByteSize() == 4)
+ load_addr &= 0xFFFFFFFF;
+
+ if (target.GetSectionLoadList().SetSectionLoadAddress(section_sp,
+ load_addr))
+ ++num_loaded_sections;
}
+ }
+ return num_loaded_sections > 0;
}
- return false;
+ }
+ return false;
}
-ByteOrder
-ObjectFileELF::GetByteOrder() const
-{
- if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
- return eByteOrderBig;
- if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
- return eByteOrderLittle;
- return eByteOrderInvalid;
+ByteOrder ObjectFileELF::GetByteOrder() const {
+ if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
+ return eByteOrderBig;
+ if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
+ return eByteOrderLittle;
+ return eByteOrderInvalid;
}
-uint32_t
-ObjectFileELF::GetAddressByteSize() const
-{
- return m_data.GetAddressByteSize();
+uint32_t ObjectFileELF::GetAddressByteSize() const {
+ return m_data.GetAddressByteSize();
}
-AddressClass
-ObjectFileELF::GetAddressClass (addr_t file_addr)
-{
- Symtab* symtab = GetSymtab();
- if (!symtab)
- return eAddressClassUnknown;
+AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
+ Symtab *symtab = GetSymtab();
+ if (!symtab)
+ return eAddressClassUnknown;
- // The address class is determined based on the symtab. Ask it from the object file what
- // contains the symtab information.
- ObjectFile* symtab_objfile = symtab->GetObjectFile();
- if (symtab_objfile != nullptr && symtab_objfile != this)
- return symtab_objfile->GetAddressClass(file_addr);
+ // The address class is determined based on the symtab. Ask it from the object
+ // file what
+ // contains the symtab information.
+ ObjectFile *symtab_objfile = symtab->GetObjectFile();
+ if (symtab_objfile != nullptr && symtab_objfile != this)
+ return symtab_objfile->GetAddressClass(file_addr);
- auto res = ObjectFile::GetAddressClass (file_addr);
- if (res != eAddressClassCode)
- return res;
+ auto res = ObjectFile::GetAddressClass(file_addr);
+ if (res != eAddressClassCode)
+ return res;
- auto ub = m_address_class_map.upper_bound(file_addr);
- if (ub == m_address_class_map.begin())
- {
- // No entry in the address class map before the address. Return
- // default address class for an address in a code section.
- return eAddressClassCode;
- }
+ auto ub = m_address_class_map.upper_bound(file_addr);
+ if (ub == m_address_class_map.begin()) {
+ // No entry in the address class map before the address. Return
+ // default address class for an address in a code section.
+ return eAddressClassCode;
+ }
- // Move iterator to the address class entry preceding address
- --ub;
+ // Move iterator to the address class entry preceding address
+ --ub;
- return ub->second;
+ return ub->second;
}
-size_t
-ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
-{
- return std::distance(m_section_headers.begin(), I) + 1u;
+size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) {
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
-size_t
-ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const
-{
- return std::distance(m_section_headers.begin(), I) + 1u;
+size_t ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const {
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
-bool
-ObjectFileELF::ParseHeader()
-{
- lldb::offset_t offset = 0;
- if (!m_header.Parse(m_data, &offset))
- return false;
+bool ObjectFileELF::ParseHeader() {
+ lldb::offset_t offset = 0;
+ if (!m_header.Parse(m_data, &offset))
+ return false;
+
+ if (!IsInMemory())
+ return true;
- if (!IsInMemory())
- return true;
+ // For in memory object files m_data might not contain the full object file.
+ // Try to load it
+ // until the end of the "Section header table" what is at the end of the ELF
+ // file.
+ addr_t file_size = m_header.e_shoff + m_header.e_shnum * m_header.e_shentsize;
+ if (m_data.GetByteSize() < file_size) {
+ ProcessSP process_sp(m_process_wp.lock());
+ if (!process_sp)
+ return false;
- // For in memory object files m_data might not contain the full object file. Try to load it
- // until the end of the "Section header table" what is at the end of the ELF file.
- addr_t file_size = m_header.e_shoff + m_header.e_shnum * m_header.e_shentsize;
- if (m_data.GetByteSize() < file_size)
- {
- ProcessSP process_sp (m_process_wp.lock());
- if (!process_sp)
- return false;
-
- DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
- if (!data_sp)
- return false;
- m_data.SetData(data_sp, 0, file_size);
- }
+ DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
+ if (!data_sp)
+ return false;
+ m_data.SetData(data_sp, 0, file_size);
+ }
- return true;
+ return true;
}
-bool
-ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
-{
- // Need to parse the section list to get the UUIDs, so make sure that's been done.
- if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
- return false;
-
- if (m_uuid.IsValid())
- {
- // We have the full build id uuid.
- *uuid = m_uuid;
- return true;
- }
- else if (GetType() == ObjectFile::eTypeCoreFile)
- {
- uint32_t core_notes_crc = 0;
-
- if (!ParseProgramHeaders())
- return false;
-
- core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
-
- if (core_notes_crc)
- {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
- // look different form .gnu_debuglink crc - followed by 4 bytes of note
- // segments crc.
- uint32_t uuidt[4] = { g_core_uuid_magic, core_notes_crc, 0, 0 };
- m_uuid.SetBytes (uuidt, sizeof(uuidt));
- }
- }
- else
- {
- if (!m_gnu_debuglink_crc)
- m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 (m_data.GetDataStart(), m_data.GetByteSize());
- if (m_gnu_debuglink_crc)
- {
- // Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = { m_gnu_debuglink_crc, 0, 0, 0 };
- m_uuid.SetBytes (uuidt, sizeof(uuidt));
- }
- }
+bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
+ // Need to parse the section list to get the UUIDs, so make sure that's been
+ // done.
+ if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
+ return false;
+
+ if (m_uuid.IsValid()) {
+ // We have the full build id uuid.
+ *uuid = m_uuid;
+ return true;
+ } else if (GetType() == ObjectFile::eTypeCoreFile) {
+ uint32_t core_notes_crc = 0;
+
+ if (!ParseProgramHeaders())
+ return false;
+
+ core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
- if (m_uuid.IsValid())
- {
- *uuid = m_uuid;
- return true;
+ if (core_notes_crc) {
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
+ // look different form .gnu_debuglink crc - followed by 4 bytes of note
+ // segments crc.
+ uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
+ m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ }
+ } else {
+ if (!m_gnu_debuglink_crc)
+ m_gnu_debuglink_crc =
+ calc_gnu_debuglink_crc32(m_data.GetDataStart(), m_data.GetByteSize());
+ if (m_gnu_debuglink_crc) {
+ // Use 4 bytes of crc from the .gnu_debuglink section.
+ uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0};
+ m_uuid.SetBytes(uuidt, sizeof(uuidt));
}
+ }
- return false;
+ if (m_uuid.IsValid()) {
+ *uuid = m_uuid;
+ return true;
+ }
+
+ return false;
}
-lldb_private::FileSpecList
-ObjectFileELF::GetDebugSymbolFilePaths()
-{
- FileSpecList file_spec_list;
+lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() {
+ FileSpecList file_spec_list;
- if (!m_gnu_debuglink_file.empty())
- {
- FileSpec file_spec (m_gnu_debuglink_file.c_str(), false);
- file_spec_list.Append (file_spec);
- }
- return file_spec_list;
+ if (!m_gnu_debuglink_file.empty()) {
+ FileSpec file_spec(m_gnu_debuglink_file.c_str(), false);
+ file_spec_list.Append(file_spec);
+ }
+ return file_spec_list;
}
-uint32_t
-ObjectFileELF::GetDependentModules(FileSpecList &files)
-{
- size_t num_modules = ParseDependentModules();
- uint32_t num_specs = 0;
+uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) {
+ size_t num_modules = ParseDependentModules();
+ uint32_t num_specs = 0;
- for (unsigned i = 0; i < num_modules; ++i)
- {
- if (files.AppendIfUnique(m_filespec_ap->GetFileSpecAtIndex(i)))
- num_specs++;
- }
+ for (unsigned i = 0; i < num_modules; ++i) {
+ if (files.AppendIfUnique(m_filespec_ap->GetFileSpecAtIndex(i)))
+ num_specs++;
+ }
- return num_specs;
+ return num_specs;
}
-Address
-ObjectFileELF::GetImageInfoAddress(Target *target)
-{
- if (!ParseDynamicSymbols())
- return Address();
+Address ObjectFileELF::GetImageInfoAddress(Target *target) {
+ if (!ParseDynamicSymbols())
+ return Address();
- SectionList *section_list = GetSectionList();
- if (!section_list)
- return Address();
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return Address();
- // Find the SHT_DYNAMIC (.dynamic) section.
- SectionSP dynsym_section_sp (section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true));
- if (!dynsym_section_sp)
- return Address();
- assert (dynsym_section_sp->GetObjectFile() == this);
+ // Find the SHT_DYNAMIC (.dynamic) section.
+ SectionSP dynsym_section_sp(
+ section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true));
+ if (!dynsym_section_sp)
+ return Address();
+ assert(dynsym_section_sp->GetObjectFile() == this);
+
+ user_id_t dynsym_id = dynsym_section_sp->GetID();
+ const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
+ if (!dynsym_hdr)
+ return Address();
- user_id_t dynsym_id = dynsym_section_sp->GetID();
- const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
- if (!dynsym_hdr)
+ for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) {
+ ELFDynamic &symbol = m_dynamic_symbols[i];
+
+ if (symbol.d_tag == DT_DEBUG) {
+ // Compute the offset as the number of previous entries plus the
+ // size of d_tag.
+ addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+ return Address(dynsym_section_sp, offset);
+ }
+ // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP
+ // exists in non-PIE.
+ else if ((symbol.d_tag == DT_MIPS_RLD_MAP ||
+ symbol.d_tag == DT_MIPS_RLD_MAP_REL) &&
+ target) {
+ addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+ addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
+ if (dyn_base == LLDB_INVALID_ADDRESS)
return Address();
- for (size_t i = 0; i < m_dynamic_symbols.size(); ++i)
- {
- ELFDynamic &symbol = m_dynamic_symbols[i];
-
- if (symbol.d_tag == DT_DEBUG)
- {
- // Compute the offset as the number of previous entries plus the
- // size of d_tag.
- addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
- return Address(dynsym_section_sp, offset);
- }
- // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP exists in non-PIE.
- else if ((symbol.d_tag == DT_MIPS_RLD_MAP || symbol.d_tag == DT_MIPS_RLD_MAP_REL) && target)
- {
- addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
- addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
- if (dyn_base == LLDB_INVALID_ADDRESS)
- return Address();
-
- Error error;
- if (symbol.d_tag == DT_MIPS_RLD_MAP)
- {
- // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
- Address addr;
- if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
- return addr;
- }
- if (symbol.d_tag == DT_MIPS_RLD_MAP_REL)
- {
- // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, relative to the address of the tag.
- uint64_t rel_offset;
- rel_offset = target->ReadUnsignedIntegerFromMemory(dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
- if (error.Success() && rel_offset != UINT64_MAX)
- {
- Address addr;
- addr_t debug_ptr_address = dyn_base + (offset - GetAddressByteSize()) + rel_offset;
- addr.SetOffset (debug_ptr_address);
- return addr;
- }
- }
- }
+ Error error;
+ if (symbol.d_tag == DT_MIPS_RLD_MAP) {
+ // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
+ Address addr;
+ if (target->ReadPointerFromMemory(dyn_base + offset, false, error,
+ addr))
+ return addr;
+ }
+ if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) {
+ // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer,
+ // relative to the address of the tag.
+ uint64_t rel_offset;
+ rel_offset = target->ReadUnsignedIntegerFromMemory(
+ dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
+ if (error.Success() && rel_offset != UINT64_MAX) {
+ Address addr;
+ addr_t debug_ptr_address =
+ dyn_base + (offset - GetAddressByteSize()) + rel_offset;
+ addr.SetOffset(debug_ptr_address);
+ return addr;
+ }
+ }
}
+ }
- return Address();
+ return Address();
}
-lldb_private::Address
-ObjectFileELF::GetEntryPointAddress ()
-{
- if (m_entry_point_address.IsValid())
- return m_entry_point_address;
+lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
+ if (m_entry_point_address.IsValid())
+ return m_entry_point_address;
- if (!ParseHeader() || !IsExecutable())
- return m_entry_point_address;
+ if (!ParseHeader() || !IsExecutable())
+ return m_entry_point_address;
- SectionList *section_list = GetSectionList();
- addr_t offset = m_header.e_entry;
+ SectionList *section_list = GetSectionList();
+ addr_t offset = m_header.e_entry;
- if (!section_list)
- m_entry_point_address.SetOffset(offset);
- else
- m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
- return m_entry_point_address;
+ if (!section_list)
+ m_entry_point_address.SetOffset(offset);
+ else
+ m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
+ return m_entry_point_address;
}
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
-size_t
-ObjectFileELF::ParseDependentModules()
-{
- if (m_filespec_ap.get())
- return m_filespec_ap->GetSize();
+size_t ObjectFileELF::ParseDependentModules() {
+ if (m_filespec_ap.get())
+ return m_filespec_ap->GetSize();
- m_filespec_ap.reset(new FileSpecList());
+ m_filespec_ap.reset(new FileSpecList());
- if (!ParseSectionHeaders())
- return 0;
+ if (!ParseSectionHeaders())
+ return 0;
- SectionList *section_list = GetSectionList();
- if (!section_list)
- return 0;
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return 0;
- // Find the SHT_DYNAMIC section.
- Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
- if (!dynsym)
- return 0;
- assert (dynsym->GetObjectFile() == this);
-
- const ELFSectionHeaderInfo *header = GetSectionHeaderByIndex (dynsym->GetID());
- if (!header)
- return 0;
- // sh_link: section header index of string table used by entries in the section.
- Section *dynstr = section_list->FindSectionByID (header->sh_link + 1).get();
- if (!dynstr)
- return 0;
-
- DataExtractor dynsym_data;
- DataExtractor dynstr_data;
- if (ReadSectionData(dynsym, dynsym_data) &&
- ReadSectionData(dynstr, dynstr_data))
- {
- ELFDynamic symbol;
- const lldb::offset_t section_size = dynsym_data.GetByteSize();
- lldb::offset_t offset = 0;
-
- // The only type of entries we are concerned with are tagged DT_NEEDED,
- // yielding the name of a required library.
- while (offset < section_size)
- {
- if (!symbol.Parse(dynsym_data, &offset))
- break;
+ // Find the SHT_DYNAMIC section.
+ Section *dynsym =
+ section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)
+ .get();
+ if (!dynsym)
+ return 0;
+ assert(dynsym->GetObjectFile() == this);
- if (symbol.d_tag != DT_NEEDED)
- continue;
+ const ELFSectionHeaderInfo *header = GetSectionHeaderByIndex(dynsym->GetID());
+ if (!header)
+ return 0;
+ // sh_link: section header index of string table used by entries in the
+ // section.
+ Section *dynstr = section_list->FindSectionByID(header->sh_link + 1).get();
+ if (!dynstr)
+ return 0;
- uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
- const char *lib_name = dynstr_data.PeekCStr(str_index);
- m_filespec_ap->Append(FileSpec(lib_name, true));
- }
+ DataExtractor dynsym_data;
+ DataExtractor dynstr_data;
+ if (ReadSectionData(dynsym, dynsym_data) &&
+ ReadSectionData(dynstr, dynstr_data)) {
+ ELFDynamic symbol;
+ const lldb::offset_t section_size = dynsym_data.GetByteSize();
+ lldb::offset_t offset = 0;
+
+ // The only type of entries we are concerned with are tagged DT_NEEDED,
+ // yielding the name of a required library.
+ while (offset < section_size) {
+ if (!symbol.Parse(dynsym_data, &offset))
+ break;
+
+ if (symbol.d_tag != DT_NEEDED)
+ continue;
+
+ uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
+ const char *lib_name = dynstr_data.PeekCStr(str_index);
+ m_filespec_ap->Append(FileSpec(lib_name, true));
}
+ }
- return m_filespec_ap->GetSize();
+ return m_filespec_ap->GetSize();
}
//----------------------------------------------------------------------
// GetProgramHeaderInfo
//----------------------------------------------------------------------
-size_t
-ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
- const SetDataFunction &set_data,
- const ELFHeader &header)
-{
- // We have already parsed the program headers
- if (!program_headers.empty())
- return program_headers.size();
-
- // If there are no program headers to read we are done.
- if (header.e_phnum == 0)
- return 0;
-
- program_headers.resize(header.e_phnum);
- if (program_headers.size() != header.e_phnum)
- return 0;
+size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
+ const SetDataFunction &set_data,
+ const ELFHeader &header) {
+ // We have already parsed the program headers
+ if (!program_headers.empty())
+ return program_headers.size();
- const size_t ph_size = header.e_phnum * header.e_phentsize;
- const elf_off ph_offset = header.e_phoff;
- DataExtractor data;
- if (set_data(data, ph_offset, ph_size) != ph_size)
- return 0;
+ // If there are no program headers to read we are done.
+ if (header.e_phnum == 0)
+ return 0;
- uint32_t idx;
- lldb::offset_t offset;
- for (idx = 0, offset = 0; idx < header.e_phnum; ++idx)
- {
- if (program_headers[idx].Parse(data, &offset) == false)
- break;
- }
+ program_headers.resize(header.e_phnum);
+ if (program_headers.size() != header.e_phnum)
+ return 0;
+
+ const size_t ph_size = header.e_phnum * header.e_phentsize;
+ const elf_off ph_offset = header.e_phoff;
+ DataExtractor data;
+ if (set_data(data, ph_offset, ph_size) != ph_size)
+ return 0;
- if (idx < program_headers.size())
- program_headers.resize(idx);
+ uint32_t idx;
+ lldb::offset_t offset;
+ for (idx = 0, offset = 0; idx < header.e_phnum; ++idx) {
+ if (program_headers[idx].Parse(data, &offset) == false)
+ break;
+ }
- return program_headers.size();
+ if (idx < program_headers.size())
+ program_headers.resize(idx);
+ return program_headers.size();
}
//----------------------------------------------------------------------
// ParseProgramHeaders
//----------------------------------------------------------------------
-size_t
-ObjectFileELF::ParseProgramHeaders()
-{
- using namespace std::placeholders;
- return GetProgramHeaderInfo(m_program_headers,
- std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3),
- m_header);
+size_t ObjectFileELF::ParseProgramHeaders() {
+ using namespace std::placeholders;
+ return GetProgramHeaderInfo(
+ m_program_headers,
+ std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2,
+ _3),
+ m_header);
}
lldb_private::Error
-ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
- Error error;
-
- lldb::offset_t offset = 0;
-
- while (true)
- {
- // Parse the note header. If this fails, bail out.
- const lldb::offset_t note_offset = offset;
- ELFNote note = ELFNote();
- if (!note.Parse(data, &offset))
- {
- // We're done.
+ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
+ lldb_private::ArchSpec &arch_spec,
+ lldb_private::UUID &uuid) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES));
+ Error error;
+
+ lldb::offset_t offset = 0;
+
+ while (true) {
+ // Parse the note header. If this fails, bail out.
+ const lldb::offset_t note_offset = offset;
+ ELFNote note = ELFNote();
+ if (!note.Parse(data, &offset)) {
+ // We're done.
+ return error;
+ }
+
+ if (log)
+ log->Printf("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32,
+ __FUNCTION__, note.n_name.c_str(), note.n_type);
+
+ // Process FreeBSD ELF notes.
+ if ((note.n_name == LLDB_NT_OWNER_FREEBSD) &&
+ (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
+ (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE)) {
+ // Pull out the min version info.
+ uint32_t version_info;
+ if (data.GetU32(&offset, &version_info, 1) == nullptr) {
+ error.SetErrorString("failed to read FreeBSD ABI note payload");
+ return error;
+ }
+
+ // Convert the version info into a major/minor number.
+ const uint32_t version_major = version_info / 100000;
+ const uint32_t version_minor = (version_info / 1000) % 100;
+
+ char os_name[32];
+ snprintf(os_name, sizeof(os_name), "freebsd%" PRIu32 ".%" PRIu32,
+ version_major, version_minor);
+
+ // Set the elf OS version to FreeBSD. Also clear the vendor.
+ arch_spec.GetTriple().setOSName(os_name);
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
+
+ if (log)
+ log->Printf("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32
+ ".%" PRIu32,
+ __FUNCTION__, version_major, version_minor,
+ static_cast<uint32_t>(version_info % 1000));
+ }
+ // Process GNU ELF notes.
+ else if (note.n_name == LLDB_NT_OWNER_GNU) {
+ switch (note.n_type) {
+ case LLDB_NT_GNU_ABI_TAG:
+ if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE) {
+ // Pull out the min OS version supporting the ABI.
+ uint32_t version_info[4];
+ if (data.GetU32(&offset, &version_info[0], note.n_descsz / 4) ==
+ nullptr) {
+ error.SetErrorString("failed to read GNU ABI note payload");
return error;
- }
-
- if (log)
- log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type);
-
- // Process FreeBSD ELF notes.
- if ((note.n_name == LLDB_NT_OWNER_FREEBSD) &&
- (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
- (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))
- {
- // Pull out the min version info.
- uint32_t version_info;
- if (data.GetU32 (&offset, &version_info, 1) == nullptr)
- {
- error.SetErrorString ("failed to read FreeBSD ABI note payload");
- return error;
- }
-
- // Convert the version info into a major/minor number.
- const uint32_t version_major = version_info / 100000;
- const uint32_t version_minor = (version_info / 1000) % 100;
-
- char os_name[32];
- snprintf (os_name, sizeof (os_name), "freebsd%" PRIu32 ".%" PRIu32, version_major, version_minor);
-
- // Set the elf OS version to FreeBSD. Also clear the vendor.
- arch_spec.GetTriple ().setOSName (os_name);
- arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
+ }
+ // Set the OS per the OS field.
+ switch (version_info[0]) {
+ case LLDB_NT_GNU_ABI_OS_LINUX:
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple().setVendor(
+ llvm::Triple::VendorType::UnknownVendor);
if (log)
- log->Printf ("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_major, version_minor, static_cast<uint32_t> (version_info % 1000));
- }
- // Process GNU ELF notes.
- else if (note.n_name == LLDB_NT_OWNER_GNU)
- {
- switch (note.n_type)
- {
- case LLDB_NT_GNU_ABI_TAG:
- if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)
- {
- // Pull out the min OS version supporting the ABI.
- uint32_t version_info[4];
- if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr)
- {
- error.SetErrorString ("failed to read GNU ABI note payload");
- return error;
- }
-
- // Set the OS per the OS field.
- switch (version_info[0])
- {
- case LLDB_NT_GNU_ABI_OS_LINUX:
- arch_spec.GetTriple ().setOS (llvm::Triple::OSType::Linux);
- arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
- if (log)
- log->Printf ("ObjectFileELF::%s detected Linux, min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
- // FIXME we have the minimal version number, we could be propagating that. version_info[1] = OS Major, version_info[2] = OS Minor, version_info[3] = Revision.
- break;
- case LLDB_NT_GNU_ABI_OS_HURD:
- arch_spec.GetTriple ().setOS (llvm::Triple::OSType::UnknownOS);
- arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
- if (log)
- log->Printf ("ObjectFileELF::%s detected Hurd (unsupported), min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
- break;
- case LLDB_NT_GNU_ABI_OS_SOLARIS:
- arch_spec.GetTriple ().setOS (llvm::Triple::OSType::Solaris);
- arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
- if (log)
- log->Printf ("ObjectFileELF::%s detected Solaris, min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[1], version_info[2], version_info[3]);
- break;
- default:
- if (log)
- log->Printf ("ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, __FUNCTION__, version_info[0], version_info[1], version_info[2], version_info[3]);
- break;
- }
- }
- break;
-
- case LLDB_NT_GNU_BUILD_ID_TAG:
- // Only bother processing this if we don't already have the uuid set.
- if (!uuid.IsValid())
- {
- // 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a build-id of a different
- // length. Accept it as long as it's at least 4 bytes as it will be better than our own crc32.
- if (note.n_descsz >= 4 && note.n_descsz <= 20)
- {
- uint8_t uuidbuf[20];
- if (data.GetU8 (&offset, &uuidbuf, note.n_descsz) == nullptr)
- {
- error.SetErrorString ("failed to read GNU_BUILD_ID note payload");
- return error;
- }
-
- // Save the build id as the UUID for the module.
- uuid.SetBytes (uuidbuf, note.n_descsz);
- }
- }
- break;
- }
- }
- // Process NetBSD ELF notes.
- else if ((note.n_name == LLDB_NT_OWNER_NETBSD) &&
- (note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
- (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))
- {
- // Pull out the min version info.
- uint32_t version_info;
- if (data.GetU32 (&offset, &version_info, 1) == nullptr)
- {
- error.SetErrorString ("failed to read NetBSD ABI note payload");
- return error;
- }
-
- // Set the elf OS version to NetBSD. Also clear the vendor.
- arch_spec.GetTriple ().setOS (llvm::Triple::OSType::NetBSD);
- arch_spec.GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor);
-
+ log->Printf(
+ "ObjectFileELF::%s detected Linux, min version %" PRIu32
+ ".%" PRIu32 ".%" PRIu32,
+ __FUNCTION__, version_info[1], version_info[2],
+ version_info[3]);
+ // FIXME we have the minimal version number, we could be propagating
+ // that. version_info[1] = OS Major, version_info[2] = OS Minor,
+ // version_info[3] = Revision.
+ break;
+ case LLDB_NT_GNU_ABI_OS_HURD:
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
+ arch_spec.GetTriple().setVendor(
+ llvm::Triple::VendorType::UnknownVendor);
if (log)
- log->Printf ("ObjectFileELF::%s detected NetBSD, min version constant %" PRIu32, __FUNCTION__, version_info);
+ log->Printf("ObjectFileELF::%s detected Hurd (unsupported), min "
+ "version %" PRIu32 ".%" PRIu32 ".%" PRIu32,
+ __FUNCTION__, version_info[1], version_info[2],
+ version_info[3]);
+ break;
+ case LLDB_NT_GNU_ABI_OS_SOLARIS:
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Solaris);
+ arch_spec.GetTriple().setVendor(
+ llvm::Triple::VendorType::UnknownVendor);
+ if (log)
+ log->Printf(
+ "ObjectFileELF::%s detected Solaris, min version %" PRIu32
+ ".%" PRIu32 ".%" PRIu32,
+ __FUNCTION__, version_info[1], version_info[2],
+ version_info[3]);
+ break;
+ default:
+ if (log)
+ log->Printf(
+ "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32
+ ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32,
+ __FUNCTION__, version_info[0], version_info[1],
+ version_info[2], version_info[3]);
+ break;
+ }
}
- // Process CSR kalimba notes
- else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
- (note.n_name == LLDB_NT_OWNER_CSR))
- {
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
- arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
+ break;
- // TODO At some point the description string could be processed.
- // It could provide a steer towards the kalimba variant which
- // this ELF targets.
- if(note.n_descsz)
- {
- const char *cstr = data.GetCStr(&offset, llvm::alignTo (note.n_descsz, 4));
- (void)cstr;
- }
- }
- else if (note.n_name == LLDB_NT_OWNER_ANDROID)
- {
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
- arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android);
+ case LLDB_NT_GNU_BUILD_ID_TAG:
+ // Only bother processing this if we don't already have the uuid set.
+ if (!uuid.IsValid()) {
+ // 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a
+ // build-id of a different
+ // length. Accept it as long as it's at least 4 bytes as it will be
+ // better than our own crc32.
+ if (note.n_descsz >= 4 && note.n_descsz <= 20) {
+ uint8_t uuidbuf[20];
+ if (data.GetU8(&offset, &uuidbuf, note.n_descsz) == nullptr) {
+ error.SetErrorString("failed to read GNU_BUILD_ID note payload");
+ return error;
+ }
+
+ // Save the build id as the UUID for the module.
+ uuid.SetBytes(uuidbuf, note.n_descsz);
+ }
}
- else if (note.n_name == LLDB_NT_OWNER_LINUX)
- {
- // This is sometimes found in core files and usually contains extended register info
+ break;
+ }
+ }
+ // Process NetBSD ELF notes.
+ else if ((note.n_name == LLDB_NT_OWNER_NETBSD) &&
+ (note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
+ (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE)) {
+ // Pull out the min version info.
+ uint32_t version_info;
+ if (data.GetU32(&offset, &version_info, 1) == nullptr) {
+ error.SetErrorString("failed to read NetBSD ABI note payload");
+ return error;
+ }
+
+ // Set the elf OS version to NetBSD. Also clear the vendor.
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::NetBSD);
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
+
+ if (log)
+ log->Printf(
+ "ObjectFileELF::%s detected NetBSD, min version constant %" PRIu32,
+ __FUNCTION__, version_info);
+ }
+ // Process CSR kalimba notes
+ else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
+ (note.n_name == LLDB_NT_OWNER_CSR)) {
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
+ arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
+
+ // TODO At some point the description string could be processed.
+ // It could provide a steer towards the kalimba variant which
+ // this ELF targets.
+ if (note.n_descsz) {
+ const char *cstr =
+ data.GetCStr(&offset, llvm::alignTo(note.n_descsz, 4));
+ (void)cstr;
+ }
+ } else if (note.n_name == LLDB_NT_OWNER_ANDROID) {
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple().setEnvironment(
+ llvm::Triple::EnvironmentType::Android);
+ } else if (note.n_name == LLDB_NT_OWNER_LINUX) {
+ // This is sometimes found in core files and usually contains extended
+ // register info
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ } else if (note.n_name == LLDB_NT_OWNER_CORE) {
+ // Parse the NT_FILE to look for stuff in paths to shared libraries
+ // As the contents look like this in a 64 bit ELF core file:
+ // count = 0x000000000000000a (10)
+ // page_size = 0x0000000000001000 (4096)
+ // Index start end file_ofs path
+ // ===== ------------------ ------------------ ------------------
+ // -------------------------------------
+ // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000
+ // /tmp/a.out
+ // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000
+ // /tmp/a.out
+ // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001
+ // /tmp/a.out
+ // [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
+ // uint32_t
+ // For reference: see readelf source code (in binutils).
+ if (note.n_type == NT_FILE) {
+ uint64_t count = data.GetAddress(&offset);
+ const char *cstr;
+ data.GetAddress(&offset); // Skip page size
+ offset += count * 3 *
+ data.GetAddressByteSize(); // Skip all start/end/file_ofs
+ for (size_t i = 0; i < count; ++i) {
+ cstr = data.GetCStr(&offset);
+ if (cstr == nullptr) {
+ error.SetErrorStringWithFormat("ObjectFileELF::%s trying to read "
+ "at an offset after the end "
+ "(GetCStr returned nullptr)",
+ __FUNCTION__);
+ return error;
+ }
+ llvm::StringRef path(cstr);
+ if (path.startswith("/lib/x86_64-linux-gnu") ||
+ path.startswith("/lib/i386-linux-gnu")) {
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ break;
+ }
}
- else if (note.n_name == LLDB_NT_OWNER_CORE)
- {
- // Parse the NT_FILE to look for stuff in paths to shared libraries
- // As the contents look like this in a 64 bit ELF core file:
- // count = 0x000000000000000a (10)
- // page_size = 0x0000000000001000 (4096)
- // Index start end file_ofs path
- // ===== ------------------ ------------------ ------------------ -------------------------------------
- // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out
- // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
- // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
- // [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
- // In the 32 bit ELFs the count, page_size, start, end, file_ofs are uint32_t
- // For reference: see readelf source code (in binutils).
- if (note.n_type == NT_FILE)
- {
- uint64_t count = data.GetAddress(&offset);
- const char *cstr;
- data.GetAddress(&offset); // Skip page size
- offset += count * 3 * data.GetAddressByteSize(); // Skip all start/end/file_ofs
- for (size_t i=0; i<count; ++i)
- {
- cstr = data.GetCStr(&offset);
- if(cstr == nullptr)
- {
- error.SetErrorStringWithFormat("ObjectFileELF::%s trying to read at an offset after the end (GetCStr returned nullptr)", __FUNCTION__);
- return error;
- }
- llvm::StringRef path(cstr);
- if (path.startswith("/lib/x86_64-linux-gnu") || path.startswith("/lib/i386-linux-gnu"))
- {
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
- break;
- }
- }
- }
- }
-
- // Calculate the offset of the next note just in case "offset" has been used
- // to poke at the contents of the note data
- offset = note_offset + note.GetByteSize();
+ }
}
- return error;
+ // Calculate the offset of the next note just in case "offset" has been used
+ // to poke at the contents of the note data
+ offset = note_offset + note.GetByteSize();
+ }
+
+ return error;
}
-void
-ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length, ArchSpec &arch_spec)
-{
- lldb::offset_t Offset = 0;
+void ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length,
+ ArchSpec &arch_spec) {
+ lldb::offset_t Offset = 0;
- uint8_t FormatVersion = data.GetU8(&Offset);
- if (FormatVersion != llvm::ARMBuildAttrs::Format_Version)
- return;
+ uint8_t FormatVersion = data.GetU8(&Offset);
+ if (FormatVersion != llvm::ARMBuildAttrs::Format_Version)
+ return;
- Offset = Offset + sizeof(uint32_t); // Section Length
- llvm::StringRef VendorName = data.GetCStr(&Offset);
+ Offset = Offset + sizeof(uint32_t); // Section Length
+ llvm::StringRef VendorName = data.GetCStr(&Offset);
- if (VendorName != "aeabi")
- return;
+ if (VendorName != "aeabi")
+ return;
- if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment)
- arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
+ if (arch_spec.GetTriple().getEnvironment() ==
+ llvm::Triple::UnknownEnvironment)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
- while (Offset < length)
- {
- uint8_t Tag = data.GetU8(&Offset);
- uint32_t Size = data.GetU32(&Offset);
+ while (Offset < length) {
+ uint8_t Tag = data.GetU8(&Offset);
+ uint32_t Size = data.GetU32(&Offset);
- if (Tag != llvm::ARMBuildAttrs::File || Size == 0)
- continue;
+ if (Tag != llvm::ARMBuildAttrs::File || Size == 0)
+ continue;
+
+ while (Offset < length) {
+ uint64_t Tag = data.GetULEB128(&Offset);
+ switch (Tag) {
+ default:
+ if (Tag < 32)
+ data.GetULEB128(&Offset);
+ else if (Tag % 2 == 0)
+ data.GetULEB128(&Offset);
+ else
+ data.GetCStr(&Offset);
- while (Offset < length)
- {
- uint64_t Tag = data.GetULEB128(&Offset);
- switch (Tag)
- {
- default:
- if (Tag < 32)
- data.GetULEB128(&Offset);
- else if (Tag % 2 == 0)
- data.GetULEB128(&Offset);
- else
- data.GetCStr(&Offset);
-
- break;
-
- case llvm::ARMBuildAttrs::CPU_raw_name:
- case llvm::ARMBuildAttrs::CPU_name:
- data.GetCStr(&Offset);
-
- break;
-
- case llvm::ARMBuildAttrs::ABI_VFP_args:
- {
- uint64_t VFPArgs = data.GetULEB128(&Offset);
-
- if (VFPArgs == llvm::ARMBuildAttrs::BaseAAPCS)
- {
- if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment ||
- arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABIHF)
- arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
-
- arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
- }
- else if (VFPArgs == llvm::ARMBuildAttrs::HardFPAAPCS)
- {
- if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment ||
- arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABI)
- arch_spec.GetTriple().setEnvironment(llvm::Triple::EABIHF);
+ break;
- arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
- }
+ case llvm::ARMBuildAttrs::CPU_raw_name:
+ case llvm::ARMBuildAttrs::CPU_name:
+ data.GetCStr(&Offset);
- break;
- }
- }
+ break;
+
+ case llvm::ARMBuildAttrs::ABI_VFP_args: {
+ uint64_t VFPArgs = data.GetULEB128(&Offset);
+
+ if (VFPArgs == llvm::ARMBuildAttrs::BaseAAPCS) {
+ if (arch_spec.GetTriple().getEnvironment() ==
+ llvm::Triple::UnknownEnvironment ||
+ arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABIHF)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI);
+
+ arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
+ } else if (VFPArgs == llvm::ARMBuildAttrs::HardFPAAPCS) {
+ if (arch_spec.GetTriple().getEnvironment() ==
+ llvm::Triple::UnknownEnvironment ||
+ arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABI)
+ arch_spec.GetTriple().setEnvironment(llvm::Triple::EABIHF);
+
+ arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
}
+
+ break;
+ }
+ }
}
+ }
}
//----------------------------------------------------------------------
// GetSectionHeaderInfo
//----------------------------------------------------------------------
-size_t
-ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,
- const SetDataFunction &set_data,
- const elf::ELFHeader &header,
- lldb_private::UUID &uuid,
- std::string &gnu_debuglink_file,
- uint32_t &gnu_debuglink_crc,
- ArchSpec &arch_spec)
-{
- // Don't reparse the section headers if we already did that.
- if (!section_headers.empty())
- return section_headers.size();
-
- // Only initialize the arch_spec to okay defaults if they're not already set.
- // We'll refine this with note data as we parse the notes.
- if (arch_spec.GetTriple ().getOS () == llvm::Triple::OSType::UnknownOS)
- {
- llvm::Triple::OSType ostype;
- llvm::Triple::OSType spec_ostype;
- const uint32_t sub_type = subTypeFromElfHeader(header);
- arch_spec.SetArchitecture (eArchTypeELF, header.e_machine, sub_type, header.e_ident[EI_OSABI]);
- //
- // Validate if it is ok to remove GetOsFromOSABI
- GetOsFromOSABI (header.e_ident[EI_OSABI], ostype);
- spec_ostype = arch_spec.GetTriple ().getOS ();
- assert(spec_ostype == ostype);
+size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,
+ const SetDataFunction &set_data,
+ const elf::ELFHeader &header,
+ lldb_private::UUID &uuid,
+ std::string &gnu_debuglink_file,
+ uint32_t &gnu_debuglink_crc,
+ ArchSpec &arch_spec) {
+ // Don't reparse the section headers if we already did that.
+ if (!section_headers.empty())
+ return section_headers.size();
+
+ // Only initialize the arch_spec to okay defaults if they're not already set.
+ // We'll refine this with note data as we parse the notes.
+ if (arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS) {
+ llvm::Triple::OSType ostype;
+ llvm::Triple::OSType spec_ostype;
+ const uint32_t sub_type = subTypeFromElfHeader(header);
+ arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
+ header.e_ident[EI_OSABI]);
+ //
+ // Validate if it is ok to remove GetOsFromOSABI
+ GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
+ spec_ostype = arch_spec.GetTriple().getOS();
+ assert(spec_ostype == ostype);
+ }
+
+ if (arch_spec.GetMachine() == llvm::Triple::mips ||
+ arch_spec.GetMachine() == llvm::Triple::mipsel ||
+ arch_spec.GetMachine() == llvm::Triple::mips64 ||
+ arch_spec.GetMachine() == llvm::Triple::mips64el) {
+ switch (header.e_flags & llvm::ELF::EF_MIPS_ARCH_ASE) {
+ case llvm::ELF::EF_MIPS_MICROMIPS:
+ arch_spec.SetFlags(ArchSpec::eMIPSAse_micromips);
+ break;
+ case llvm::ELF::EF_MIPS_ARCH_ASE_M16:
+ arch_spec.SetFlags(ArchSpec::eMIPSAse_mips16);
+ break;
+ case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX:
+ arch_spec.SetFlags(ArchSpec::eMIPSAse_mdmx);
+ break;
+ default:
+ break;
}
+ }
- if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel
- || arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el)
- {
- switch (header.e_flags & llvm::ELF::EF_MIPS_ARCH_ASE)
- {
- case llvm::ELF::EF_MIPS_MICROMIPS:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_micromips);
+ if (arch_spec.GetMachine() == llvm::Triple::arm ||
+ arch_spec.GetMachine() == llvm::Triple::thumb) {
+ if (header.e_flags & llvm::ELF::EF_ARM_SOFT_FLOAT)
+ arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float);
+ else if (header.e_flags & llvm::ELF::EF_ARM_VFP_FLOAT)
+ arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float);
+ }
+
+ // If there are no section headers we are done.
+ if (header.e_shnum == 0)
+ return 0;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES));
+
+ section_headers.resize(header.e_shnum);
+ if (section_headers.size() != header.e_shnum)
+ return 0;
+
+ const size_t sh_size = header.e_shnum * header.e_shentsize;
+ const elf_off sh_offset = header.e_shoff;
+ DataExtractor sh_data;
+ if (set_data(sh_data, sh_offset, sh_size) != sh_size)
+ return 0;
+
+ uint32_t idx;
+ lldb::offset_t offset;
+ for (idx = 0, offset = 0; idx < header.e_shnum; ++idx) {
+ if (section_headers[idx].Parse(sh_data, &offset) == false)
+ break;
+ }
+ if (idx < section_headers.size())
+ section_headers.resize(idx);
+
+ const unsigned strtab_idx = header.e_shstrndx;
+ if (strtab_idx && strtab_idx < section_headers.size()) {
+ const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx];
+ const size_t byte_size = sheader.sh_size;
+ const Elf64_Off offset = sheader.sh_offset;
+ lldb_private::DataExtractor shstr_data;
+
+ if (set_data(shstr_data, offset, byte_size) == byte_size) {
+ for (SectionHeaderCollIter I = section_headers.begin();
+ I != section_headers.end(); ++I) {
+ static ConstString g_sect_name_gnu_debuglink(".gnu_debuglink");
+ const ELFSectionHeaderInfo &sheader = *I;
+ const uint64_t section_size =
+ sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;
+ ConstString name(shstr_data.PeekCStr(I->sh_name));
+
+ I->section_name = name;
+
+ if (arch_spec.IsMIPS()) {
+ uint32_t arch_flags = arch_spec.GetFlags();
+ DataExtractor data;
+ if (sheader.sh_type == SHT_MIPS_ABIFLAGS) {
+
+ if (section_size && (set_data(data, sheader.sh_offset,
+ section_size) == section_size)) {
+ // MIPS ASE Mask is at offset 12 in MIPS.abiflags section
+ lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0
+ arch_flags |= data.GetU32(&offset);
+
+ // The floating point ABI is at offset 7
+ offset = 7;
+ switch (data.GetU8(&offset)) {
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_ANY;
break;
- case llvm::ELF::EF_MIPS_ARCH_ASE_M16:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_mips16);
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_DOUBLE;
break;
- case llvm::ELF::EF_MIPS_ARCH_ASE_MDMX:
- arch_spec.SetFlags (ArchSpec::eMIPSAse_mdmx);
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SINGLE;
break;
- default:
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT;
break;
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_OLD_64;
+ break;
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_XX;
+ break;
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_64:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64;
+ break;
+ case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A:
+ arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64A;
+ break;
+ }
+ }
+ }
+ // Settings appropriate ArchSpec ABI Flags
+ switch (header.e_flags & llvm::ELF::EF_MIPS_ABI) {
+ case llvm::ELF::EF_MIPS_ABI_O32:
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;
+ break;
+ case EF_MIPS_ABI_O64:
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_O64;
+ break;
+ case EF_MIPS_ABI_EABI32:
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI32;
+ break;
+ case EF_MIPS_ABI_EABI64:
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI64;
+ break;
+ default:
+ // ABI Mask doesn't cover N32 and N64 ABI.
+ if (header.e_ident[EI_CLASS] == llvm::ELF::ELFCLASS64)
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_N64;
+ else if (header.e_flags && llvm::ELF::EF_MIPS_ABI2)
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32;
+ break;
+ }
+ arch_spec.SetFlags(arch_flags);
}
- }
- if (arch_spec.GetMachine() == llvm::Triple::arm ||
- arch_spec.GetMachine() == llvm::Triple::thumb)
- {
- if (header.e_flags & llvm::ELF::EF_ARM_SOFT_FLOAT)
- arch_spec.SetFlags (ArchSpec::eARM_abi_soft_float);
- else if (header.e_flags & llvm::ELF::EF_ARM_VFP_FLOAT)
- arch_spec.SetFlags (ArchSpec::eARM_abi_hard_float);
- }
-
- // If there are no section headers we are done.
- if (header.e_shnum == 0)
- return 0;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MODULES));
-
- section_headers.resize(header.e_shnum);
- if (section_headers.size() != header.e_shnum)
- return 0;
-
- const size_t sh_size = header.e_shnum * header.e_shentsize;
- const elf_off sh_offset = header.e_shoff;
- DataExtractor sh_data;
- if (set_data (sh_data, sh_offset, sh_size) != sh_size)
- return 0;
-
- uint32_t idx;
- lldb::offset_t offset;
- for (idx = 0, offset = 0; idx < header.e_shnum; ++idx)
- {
- if (section_headers[idx].Parse(sh_data, &offset) == false)
- break;
- }
- if (idx < section_headers.size())
- section_headers.resize(idx);
+ if (arch_spec.GetMachine() == llvm::Triple::arm ||
+ arch_spec.GetMachine() == llvm::Triple::thumb) {
+ DataExtractor data;
- const unsigned strtab_idx = header.e_shstrndx;
- if (strtab_idx && strtab_idx < section_headers.size())
- {
- const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx];
- const size_t byte_size = sheader.sh_size;
- const Elf64_Off offset = sheader.sh_offset;
- lldb_private::DataExtractor shstr_data;
-
- if (set_data (shstr_data, offset, byte_size) == byte_size)
- {
- for (SectionHeaderCollIter I = section_headers.begin();
- I != section_headers.end(); ++I)
- {
- static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink");
- const ELFSectionHeaderInfo &sheader = *I;
- const uint64_t section_size = sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;
- ConstString name(shstr_data.PeekCStr(I->sh_name));
-
- I->section_name = name;
-
- if (arch_spec.IsMIPS())
- {
- uint32_t arch_flags = arch_spec.GetFlags ();
- DataExtractor data;
- if (sheader.sh_type == SHT_MIPS_ABIFLAGS)
- {
-
- if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
- {
- // MIPS ASE Mask is at offset 12 in MIPS.abiflags section
- lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0
- arch_flags |= data.GetU32 (&offset);
-
- // The floating point ABI is at offset 7
- offset = 7;
- switch (data.GetU8 (&offset))
- {
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_ANY;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_DOUBLE;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SINGLE;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64 :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_OLD_64;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_XX;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_64 :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64;
- break;
- case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A :
- arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64A;
- break;
- }
- }
- }
- // Settings appropriate ArchSpec ABI Flags
- switch(header.e_flags & llvm::ELF::EF_MIPS_ABI)
- {
- case llvm::ELF::EF_MIPS_ABI_O32:
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;
- break;
- case EF_MIPS_ABI_O64:
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_O64;
- break;
- case EF_MIPS_ABI_EABI32:
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI32;
- break;
- case EF_MIPS_ABI_EABI64:
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI64;
- break;
- default:
- // ABI Mask doesn't cover N32 and N64 ABI.
- if (header.e_ident[EI_CLASS] == llvm::ELF::ELFCLASS64)
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_N64;
- else if (header.e_flags && llvm::ELF::EF_MIPS_ABI2)
- arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32;
- break;
- }
- arch_spec.SetFlags (arch_flags);
- }
+ if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
+ set_data(data, sheader.sh_offset, section_size) == section_size)
+ ParseARMAttributes(data, section_size, arch_spec);
+ }
- if (arch_spec.GetMachine() == llvm::Triple::arm || arch_spec.GetMachine() == llvm::Triple::thumb)
- {
- DataExtractor data;
-
- if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 &&
- set_data(data, sheader.sh_offset, section_size) == section_size)
- ParseARMAttributes(data, section_size, arch_spec);
- }
+ if (name == g_sect_name_gnu_debuglink) {
+ DataExtractor data;
+ if (section_size && (set_data(data, sheader.sh_offset,
+ section_size) == section_size)) {
+ lldb::offset_t gnu_debuglink_offset = 0;
+ gnu_debuglink_file = data.GetCStr(&gnu_debuglink_offset);
+ gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4);
+ data.GetU32(&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
+ }
+ }
- if (name == g_sect_name_gnu_debuglink)
- {
- DataExtractor data;
- if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
- {
- lldb::offset_t gnu_debuglink_offset = 0;
- gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
- gnu_debuglink_offset = llvm::alignTo (gnu_debuglink_offset, 4);
- data.GetU32 (&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
- }
- }
+ // Process ELF note section entries.
+ bool is_note_header = (sheader.sh_type == SHT_NOTE);
- // Process ELF note section entries.
- bool is_note_header = (sheader.sh_type == SHT_NOTE);
+ // The section header ".note.android.ident" is stored as a
+ // PROGBITS type header but it is actually a note header.
+ static ConstString g_sect_name_android_ident(".note.android.ident");
+ if (!is_note_header && name == g_sect_name_android_ident)
+ is_note_header = true;
- // The section header ".note.android.ident" is stored as a
- // PROGBITS type header but it is actually a note header.
- static ConstString g_sect_name_android_ident (".note.android.ident");
- if (!is_note_header && name == g_sect_name_android_ident)
- is_note_header = true;
-
- if (is_note_header)
- {
- // Allow notes to refine module info.
- DataExtractor data;
- if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
- {
- Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("ObjectFileELF::%s ELF note processing failed: %s", __FUNCTION__, error.AsCString ());
- }
- }
- }
+ if (is_note_header) {
+ // Allow notes to refine module info.
+ DataExtractor data;
+ if (section_size && (set_data(data, sheader.sh_offset,
+ section_size) == section_size)) {
+ Error error = RefineModuleDetailsFromNote(data, arch_spec, uuid);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("ObjectFileELF::%s ELF note processing failed: %s",
+ __FUNCTION__, error.AsCString());
}
+ }
+ }
+ }
- // Make any unknown triple components to be unspecified unknowns.
- if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
- arch_spec.GetTriple().setVendorName (llvm::StringRef());
- if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS)
- arch_spec.GetTriple().setOSName (llvm::StringRef());
+ // Make any unknown triple components to be unspecified unknowns.
+ if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
+ arch_spec.GetTriple().setVendorName(llvm::StringRef());
+ if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS)
+ arch_spec.GetTriple().setOSName(llvm::StringRef());
- return section_headers.size();
- }
+ return section_headers.size();
}
+ }
- section_headers.clear();
- return 0;
+ section_headers.clear();
+ return 0;
}
-size_t
-ObjectFileELF::GetProgramHeaderCount()
-{
- return ParseProgramHeaders();
-}
+size_t ObjectFileELF::GetProgramHeaderCount() { return ParseProgramHeaders(); }
const elf::ELFProgramHeader *
-ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id)
-{
- if (!id || !ParseProgramHeaders())
- return NULL;
+ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id) {
+ if (!id || !ParseProgramHeaders())
+ return NULL;
- if (--id < m_program_headers.size())
- return &m_program_headers[id];
+ if (--id < m_program_headers.size())
+ return &m_program_headers[id];
- return NULL;
+ return NULL;
}
-DataExtractor
-ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
-{
- const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
- if (segment_header == NULL)
- return DataExtractor();
- return DataExtractor(m_data, segment_header->p_offset, segment_header->p_filesz);
+DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) {
+ const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
+ if (segment_header == NULL)
+ return DataExtractor();
+ return DataExtractor(m_data, segment_header->p_offset,
+ segment_header->p_filesz);
}
std::string
-ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
-{
- size_t pos = symbol_name.find('@');
- return symbol_name.substr(0, pos).str();
+ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
+ size_t pos = symbol_name.find('@');
+ return symbol_name.substr(0, pos).str();
}
//----------------------------------------------------------------------
// ParseSectionHeaders
//----------------------------------------------------------------------
-size_t
-ObjectFileELF::ParseSectionHeaders()
-{
- using namespace std::placeholders;
-
- return GetSectionHeaderInfo(m_section_headers,
- std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3),
- m_header,
- m_uuid,
- m_gnu_debuglink_file,
- m_gnu_debuglink_crc,
- m_arch_spec);
+size_t ObjectFileELF::ParseSectionHeaders() {
+ using namespace std::placeholders;
+
+ return GetSectionHeaderInfo(
+ m_section_headers,
+ std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2,
+ _3),
+ m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc, m_arch_spec);
}
-lldb::offset_t
-ObjectFileELF::SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length)
-{
- return dst.SetData(src, offset, length);
+lldb::offset_t ObjectFileELF::SetData(const lldb_private::DataExtractor &src,
+ lldb_private::DataExtractor &dst,
+ lldb::offset_t offset,
+ lldb::offset_t length) {
+ return dst.SetData(src, offset, length);
}
lldb::offset_t
-ObjectFileELF::SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length)
-{
- if (offset + length <= m_data.GetByteSize())
- return dst.SetData(m_data, offset, length);
-
- const auto process_sp = m_process_wp.lock();
- if (process_sp != nullptr)
- {
- addr_t file_size = offset + length;
-
- DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
- if (!data_sp)
- return false;
- m_data.SetData(data_sp, 0, file_size);
- }
-
+ObjectFileELF::SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst,
+ lldb::offset_t offset,
+ lldb::offset_t length) {
+ if (offset + length <= m_data.GetByteSize())
return dst.SetData(m_data, offset, length);
+
+ const auto process_sp = m_process_wp.lock();
+ if (process_sp != nullptr) {
+ addr_t file_size = offset + length;
+
+ DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
+ if (!data_sp)
+ return false;
+ m_data.SetData(data_sp, 0, file_size);
+ }
+
+ return dst.SetData(m_data, offset, length);
}
const ObjectFileELF::ELFSectionHeaderInfo *
-ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
-{
- if (!id || !ParseSectionHeaders())
- return NULL;
+ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
+ if (!id || !ParseSectionHeaders())
+ return NULL;
- if (--id < m_section_headers.size())
- return &m_section_headers[id];
+ if (--id < m_section_headers.size())
+ return &m_section_headers[id];
- return NULL;
+ return NULL;
}
-lldb::user_id_t
-ObjectFileELF::GetSectionIndexByName(const char* name)
-{
- if (!name || !name[0] || !ParseSectionHeaders())
- return 0;
- for (size_t i = 1; i < m_section_headers.size(); ++i)
- if (m_section_headers[i].section_name == ConstString(name))
- return i;
- return 0;
-}
-
-void
-ObjectFileELF::CreateSections(SectionList &unified_section_list)
-{
- if (!m_sections_ap.get() && ParseSectionHeaders())
- {
- m_sections_ap.reset(new SectionList());
-
- for (SectionHeaderCollIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I)
- {
- const ELFSectionHeaderInfo &header = *I;
-
- ConstString& name = I->section_name;
- const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
- const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
-
- static ConstString g_sect_name_text (".text");
- static ConstString g_sect_name_data (".data");
- static ConstString g_sect_name_bss (".bss");
- static ConstString g_sect_name_tdata (".tdata");
- static ConstString g_sect_name_tbss (".tbss");
- static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_addr (".debug_addr");
- static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");
- static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");
- static ConstString g_sect_name_dwarf_debug_info (".debug_info");
- static ConstString g_sect_name_dwarf_debug_line (".debug_line");
- static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_macro (".debug_macro");
- static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str (".debug_str");
- static ConstString g_sect_name_dwarf_debug_str_offsets (".debug_str_offsets");
- static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo");
- static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo");
- static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo");
- static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo");
- static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo");
- static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo");
- static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");
- static ConstString g_sect_name_eh_frame (".eh_frame");
- static ConstString g_sect_name_arm_exidx (".ARM.exidx");
- static ConstString g_sect_name_arm_extab (".ARM.extab");
- static ConstString g_sect_name_go_symtab (".gosymtab");
-
- SectionType sect_type = eSectionTypeOther;
-
- bool is_thread_specific = false;
-
- if (name == g_sect_name_text) sect_type = eSectionTypeCode;
- else if (name == g_sect_name_data) sect_type = eSectionTypeData;
- else if (name == g_sect_name_bss) sect_type = eSectionTypeZeroFill;
- else if (name == g_sect_name_tdata)
- {
- sect_type = eSectionTypeData;
- is_thread_specific = true;
- }
- else if (name == g_sect_name_tbss)
- {
- sect_type = eSectionTypeZeroFill;
- is_thread_specific = true;
- }
- // .debug_abbrev – Abbreviations used in the .debug_info section
- // .debug_aranges – Lookup table for mapping addresses to compilation units
- // .debug_frame – Call frame information
- // .debug_info – The core DWARF information section
- // .debug_line – Line number information
- // .debug_loc – Location lists used in DW_AT_location attributes
- // .debug_macinfo – Macro information
- // .debug_pubnames – Lookup table for mapping object and function names to compilation units
- // .debug_pubtypes – Lookup table for mapping type names to compilation units
- // .debug_ranges – Address ranges used in DW_AT_ranges attributes
- // .debug_str – String table used in .debug_info
- // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
- // MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
- // MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
- else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_addr) sect_type = eSectionTypeDWARFDebugAddr;
- else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
- else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
- else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (name == g_sect_name_dwarf_debug_macro) sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames;
- else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
- else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_str_offsets) sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_dwarf_debug_abbrev_dwo) sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_info_dwo) sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line_dwo) sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_macro_dwo) sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_loc_dwo) sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
- else if (name == g_sect_name_arm_exidx) sect_type = eSectionTypeARMexidx;
- else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab;
- else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab;
-
- const uint32_t permissions = ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0) |
- ((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0) |
- ((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0);
- switch (header.sh_type)
- {
- case SHT_SYMTAB:
- assert (sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFSymbolTable;
- break;
- case SHT_DYNSYM:
- assert (sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicSymbols;
- break;
- case SHT_RELA:
- case SHT_REL:
- assert (sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFRelocationEntries;
- break;
- case SHT_DYNAMIC:
- assert (sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicLinkInfo;
- break;
- }
+lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
+ if (!name || !name[0] || !ParseSectionHeaders())
+ return 0;
+ for (size_t i = 1; i < m_section_headers.size(); ++i)
+ if (m_section_headers[i].section_name == ConstString(name))
+ return i;
+ return 0;
+}
- if (eSectionTypeOther == sect_type)
- {
- // the kalimba toolchain assumes that ELF section names are free-form. It does
- // support linkscripts which (can) give rise to various arbitrarily named
- // sections being "Code" or "Data".
- sect_type = kalimbaSectionType(m_header, header);
- }
+void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
+ if (!m_sections_ap.get() && ParseSectionHeaders()) {
+ m_sections_ap.reset(new SectionList());
- const uint32_t target_bytes_size =
- (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type) ?
- m_arch_spec.GetDataByteSize() :
- eSectionTypeCode == sect_type ?
- m_arch_spec.GetCodeByteSize() : 1;
-
- elf::elf_xword log2align = (header.sh_addralign==0)
- ? 0
- : llvm::Log2_64(header.sh_addralign);
- SectionSP section_sp (new Section(GetModule(), // Module to which this section belongs.
- this, // ObjectFile to which this section belongs and should read section data from.
- SectionIndex(I), // Section ID.
- name, // Section name.
- sect_type, // Section type.
- header.sh_addr, // VM address.
- vm_size, // VM size in bytes of this section.
- header.sh_offset, // Offset of this section in the file.
- file_size, // Size of the section as found in the file.
- log2align, // Alignment of the section
- header.sh_flags, // Flags for this section.
- target_bytes_size));// Number of host bytes per target byte
-
- section_sp->SetPermissions(permissions);
- if (is_thread_specific)
- section_sp->SetIsThreadSpecific (is_thread_specific);
- m_sections_ap->AddSection(section_sp);
- }
- }
+ for (SectionHeaderCollIter I = m_section_headers.begin();
+ I != m_section_headers.end(); ++I) {
+ const ELFSectionHeaderInfo &header = *I;
- if (m_sections_ap.get())
- {
- if (GetType() == eTypeDebugInfo)
- {
- static const SectionType g_sections[] =
- {
- eSectionTypeDWARFDebugAbbrev,
- eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges,
- eSectionTypeDWARFDebugFrame,
- eSectionTypeDWARFDebugInfo,
- eSectionTypeDWARFDebugLine,
- eSectionTypeDWARFDebugLoc,
- eSectionTypeDWARFDebugMacInfo,
- eSectionTypeDWARFDebugPubNames,
- eSectionTypeDWARFDebugPubTypes,
- eSectionTypeDWARFDebugRanges,
- eSectionTypeDWARFDebugStr,
- eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable,
- };
- SectionList *elf_section_list = m_sections_ap.get();
- for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
- {
- SectionType section_type = g_sections[idx];
- SectionSP section_sp (elf_section_list->FindSectionByType (section_type, true));
- if (section_sp)
- {
- SectionSP module_section_sp (unified_section_list.FindSectionByType (section_type, true));
- if (module_section_sp)
- unified_section_list.ReplaceSection (module_section_sp->GetID(), section_sp);
- else
- unified_section_list.AddSection (section_sp);
- }
- }
- }
- else
- {
- unified_section_list = *m_sections_ap;
- }
- }
-}
+ ConstString &name = I->section_name;
+ const uint64_t file_size =
+ header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+ const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
+
+ static ConstString g_sect_name_text(".text");
+ static ConstString g_sect_name_data(".data");
+ static ConstString g_sect_name_bss(".bss");
+ static ConstString g_sect_name_tdata(".tdata");
+ static ConstString g_sect_name_tbss(".tbss");
+ static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_addr(".debug_addr");
+ static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
+ static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
+ static ConstString g_sect_name_dwarf_debug_info(".debug_info");
+ static ConstString g_sect_name_dwarf_debug_line(".debug_line");
+ static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
+ static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_macro(".debug_macro");
+ static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
+ static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
+ static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
+ static ConstString g_sect_name_dwarf_debug_str(".debug_str");
+ static ConstString g_sect_name_dwarf_debug_str_offsets(
+ ".debug_str_offsets");
+ static ConstString g_sect_name_dwarf_debug_abbrev_dwo(
+ ".debug_abbrev.dwo");
+ static ConstString g_sect_name_dwarf_debug_info_dwo(".debug_info.dwo");
+ static ConstString g_sect_name_dwarf_debug_line_dwo(".debug_line.dwo");
+ static ConstString g_sect_name_dwarf_debug_macro_dwo(".debug_macro.dwo");
+ static ConstString g_sect_name_dwarf_debug_loc_dwo(".debug_loc.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_dwo(".debug_str.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_offsets_dwo(
+ ".debug_str_offsets.dwo");
+ static ConstString g_sect_name_eh_frame(".eh_frame");
+ static ConstString g_sect_name_arm_exidx(".ARM.exidx");
+ static ConstString g_sect_name_arm_extab(".ARM.extab");
+ static ConstString g_sect_name_go_symtab(".gosymtab");
+
+ SectionType sect_type = eSectionTypeOther;
+
+ bool is_thread_specific = false;
+
+ if (name == g_sect_name_text)
+ sect_type = eSectionTypeCode;
+ else if (name == g_sect_name_data)
+ sect_type = eSectionTypeData;
+ else if (name == g_sect_name_bss)
+ sect_type = eSectionTypeZeroFill;
+ else if (name == g_sect_name_tdata) {
+ sect_type = eSectionTypeData;
+ is_thread_specific = true;
+ } else if (name == g_sect_name_tbss) {
+ sect_type = eSectionTypeZeroFill;
+ is_thread_specific = true;
+ }
+ // .debug_abbrev – Abbreviations used in the .debug_info section
+ // .debug_aranges – Lookup table for mapping addresses to compilation
+ // units
+ // .debug_frame – Call frame information
+ // .debug_info – The core DWARF information section
+ // .debug_line – Line number information
+ // .debug_loc – Location lists used in DW_AT_location attributes
+ // .debug_macinfo – Macro information
+ // .debug_pubnames – Lookup table for mapping object and function names to
+ // compilation units
+ // .debug_pubtypes – Lookup table for mapping type names to compilation
+ // units
+ // .debug_ranges – Address ranges used in DW_AT_ranges attributes
+ // .debug_str – String table used in .debug_info
+ // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
+ // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
+ // MISSING? .debug-index -
+ // http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
+ // MISSING? .debug_types - Type descriptions from DWARF 4? See
+ // http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
+ else if (name == g_sect_name_dwarf_debug_abbrev)
+ sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_addr)
+ sect_type = eSectionTypeDWARFDebugAddr;
+ else if (name == g_sect_name_dwarf_debug_aranges)
+ sect_type = eSectionTypeDWARFDebugAranges;
+ else if (name == g_sect_name_dwarf_debug_frame)
+ sect_type = eSectionTypeDWARFDebugFrame;
+ else if (name == g_sect_name_dwarf_debug_info)
+ sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line)
+ sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_loc)
+ sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_macinfo)
+ sect_type = eSectionTypeDWARFDebugMacInfo;
+ else if (name == g_sect_name_dwarf_debug_macro)
+ sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_pubnames)
+ sect_type = eSectionTypeDWARFDebugPubNames;
+ else if (name == g_sect_name_dwarf_debug_pubtypes)
+ sect_type = eSectionTypeDWARFDebugPubTypes;
+ else if (name == g_sect_name_dwarf_debug_ranges)
+ sect_type = eSectionTypeDWARFDebugRanges;
+ else if (name == g_sect_name_dwarf_debug_str)
+ sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets)
+ sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
+ sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_info_dwo)
+ sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line_dwo)
+ sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_macro_dwo)
+ sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_loc_dwo)
+ sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_str_dwo)
+ sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets_dwo)
+ sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_eh_frame)
+ sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_arm_exidx)
+ sect_type = eSectionTypeARMexidx;
+ else if (name == g_sect_name_arm_extab)
+ sect_type = eSectionTypeARMextab;
+ else if (name == g_sect_name_go_symtab)
+ sect_type = eSectionTypeGoSymtab;
+
+ const uint32_t permissions =
+ ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0) |
+ ((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0) |
+ ((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0);
+ switch (header.sh_type) {
+ case SHT_SYMTAB:
+ assert(sect_type == eSectionTypeOther);
+ sect_type = eSectionTypeELFSymbolTable;
+ break;
+ case SHT_DYNSYM:
+ assert(sect_type == eSectionTypeOther);
+ sect_type = eSectionTypeELFDynamicSymbols;
+ break;
+ case SHT_RELA:
+ case SHT_REL:
+ assert(sect_type == eSectionTypeOther);
+ sect_type = eSectionTypeELFRelocationEntries;
+ break;
+ case SHT_DYNAMIC:
+ assert(sect_type == eSectionTypeOther);
+ sect_type = eSectionTypeELFDynamicLinkInfo;
+ break;
+ }
-// Find the arm/aarch64 mapping symbol character in the given symbol name. Mapping symbols have the
-// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping symbol prefixed by
-// an arbitrary string because if a symbol prefix added to each symbol in the object file with
+ if (eSectionTypeOther == sect_type) {
+ // the kalimba toolchain assumes that ELF section names are free-form.
+ // It does
+ // support linkscripts which (can) give rise to various arbitrarily
+ // named
+ // sections being "Code" or "Data".
+ sect_type = kalimbaSectionType(m_header, header);
+ }
+
+ const uint32_t target_bytes_size =
+ (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
+ ? m_arch_spec.GetDataByteSize()
+ : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize()
+ : 1;
+
+ elf::elf_xword log2align =
+ (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
+ SectionSP section_sp(new Section(
+ GetModule(), // Module to which this section belongs.
+ this, // ObjectFile to which this section belongs and should read
+ // section data from.
+ SectionIndex(I), // Section ID.
+ name, // Section name.
+ sect_type, // Section type.
+ header.sh_addr, // VM address.
+ vm_size, // VM size in bytes of this section.
+ header.sh_offset, // Offset of this section in the file.
+ file_size, // Size of the section as found in the file.
+ log2align, // Alignment of the section
+ header.sh_flags, // Flags for this section.
+ target_bytes_size)); // Number of host bytes per target byte
+
+ section_sp->SetPermissions(permissions);
+ if (is_thread_specific)
+ section_sp->SetIsThreadSpecific(is_thread_specific);
+ m_sections_ap->AddSection(section_sp);
+ }
+ }
+
+ if (m_sections_ap.get()) {
+ if (GetType() == eTypeDebugInfo) {
+ static const SectionType g_sections[] = {
+ eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine,
+ eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo,
+ eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes,
+ eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable,
+ };
+ SectionList *elf_section_list = m_sections_ap.get();
+ for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
+ ++idx) {
+ SectionType section_type = g_sections[idx];
+ SectionSP section_sp(
+ elf_section_list->FindSectionByType(section_type, true));
+ if (section_sp) {
+ SectionSP module_section_sp(
+ unified_section_list.FindSectionByType(section_type, true));
+ if (module_section_sp)
+ unified_section_list.ReplaceSection(module_section_sp->GetID(),
+ section_sp);
+ else
+ unified_section_list.AddSection(section_sp);
+ }
+ }
+ } else {
+ unified_section_list = *m_sections_ap;
+ }
+ }
+}
+
+// Find the arm/aarch64 mapping symbol character in the given symbol name.
+// Mapping symbols have the
+// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping
+// symbol prefixed by
+// an arbitrary string because if a symbol prefix added to each symbol in the
+// object file with
// objcopy then the mapping symbols are also prefixed.
-static char
-FindArmAarch64MappingSymbol(const char* symbol_name)
-{
- if (!symbol_name)
- return '\0';
-
- const char* dollar_pos = ::strchr(symbol_name, '$');
- if (!dollar_pos || dollar_pos[1] == '\0')
- return '\0';
+static char FindArmAarch64MappingSymbol(const char *symbol_name) {
+ if (!symbol_name)
+ return '\0';
- if (dollar_pos[2] == '\0' || dollar_pos[2] == '.')
- return dollar_pos[1];
+ const char *dollar_pos = ::strchr(symbol_name, '$');
+ if (!dollar_pos || dollar_pos[1] == '\0')
return '\0';
+
+ if (dollar_pos[2] == '\0' || dollar_pos[2] == '.')
+ return dollar_pos[1];
+ return '\0';
}
-#define STO_MIPS_ISA (3 << 6)
-#define STO_MICROMIPS (2 << 6)
-#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
+#define STO_MIPS_ISA (3 << 6)
+#define STO_MICROMIPS (2 << 6)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
// private
-unsigned
-ObjectFileELF::ParseSymbols (Symtab *symtab,
- user_id_t start_id,
- SectionList *section_list,
- const size_t num_symbols,
- const DataExtractor &symtab_data,
- const DataExtractor &strtab_data)
-{
- ELFSymbol symbol;
- lldb::offset_t offset = 0;
-
- static ConstString text_section_name(".text");
- static ConstString init_section_name(".init");
- static ConstString fini_section_name(".fini");
- static ConstString ctors_section_name(".ctors");
- static ConstString dtors_section_name(".dtors");
-
- static ConstString data_section_name(".data");
- static ConstString rodata_section_name(".rodata");
- static ConstString rodata1_section_name(".rodata1");
- static ConstString data2_section_name(".data1");
- static ConstString bss_section_name(".bss");
- static ConstString opd_section_name(".opd"); // For ppc64
-
- // On Android the oatdata and the oatexec symbols in the oat and odex files covers the full
- // .text section what causes issues with displaying unusable symbol name to the user and very
- // slow unwinding speed because the instruction emulation based unwind plans try to emulate all
- // instructions in these symbols. Don't add these symbols to the symbol list as they have no
- // use for the debugger and they are causing a lot of trouble.
- // Filtering can't be restricted to Android because this special object file don't contain the
- // note section specifying the environment to Android but the custom extension and file name
- // makes it highly unlikely that this will collide with anything else.
- ConstString file_extension = m_file.GetFileNameExtension();
- bool skip_oatdata_oatexec = file_extension == ConstString("oat") || file_extension == ConstString("odex");
-
- ArchSpec arch;
- GetArchitecture(arch);
- ModuleSP module_sp(GetModule());
- SectionList* module_section_list = module_sp ? module_sp->GetSectionList() : nullptr;
-
- // Local cache to avoid doing a FindSectionByName for each symbol. The "const char*" key must
- // came from a ConstString object so they can be compared by pointer
- std::unordered_map<const char*, lldb::SectionSP> section_name_to_section;
-
- unsigned i;
- for (i = 0; i < num_symbols; ++i)
- {
- if (symbol.Parse(symtab_data, &offset) == false)
- break;
+unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
+ SectionList *section_list,
+ const size_t num_symbols,
+ const DataExtractor &symtab_data,
+ const DataExtractor &strtab_data) {
+ ELFSymbol symbol;
+ lldb::offset_t offset = 0;
+
+ static ConstString text_section_name(".text");
+ static ConstString init_section_name(".init");
+ static ConstString fini_section_name(".fini");
+ static ConstString ctors_section_name(".ctors");
+ static ConstString dtors_section_name(".dtors");
+
+ static ConstString data_section_name(".data");
+ static ConstString rodata_section_name(".rodata");
+ static ConstString rodata1_section_name(".rodata1");
+ static ConstString data2_section_name(".data1");
+ static ConstString bss_section_name(".bss");
+ static ConstString opd_section_name(".opd"); // For ppc64
+
+ // On Android the oatdata and the oatexec symbols in the oat and odex files
+ // covers the full
+ // .text section what causes issues with displaying unusable symbol name to
+ // the user and very
+ // slow unwinding speed because the instruction emulation based unwind plans
+ // try to emulate all
+ // instructions in these symbols. Don't add these symbols to the symbol list
+ // as they have no
+ // use for the debugger and they are causing a lot of trouble.
+ // Filtering can't be restricted to Android because this special object file
+ // don't contain the
+ // note section specifying the environment to Android but the custom extension
+ // and file name
+ // makes it highly unlikely that this will collide with anything else.
+ ConstString file_extension = m_file.GetFileNameExtension();
+ bool skip_oatdata_oatexec = file_extension == ConstString("oat") ||
+ file_extension == ConstString("odex");
+
+ ArchSpec arch;
+ GetArchitecture(arch);
+ ModuleSP module_sp(GetModule());
+ SectionList *module_section_list =
+ module_sp ? module_sp->GetSectionList() : nullptr;
+
+ // Local cache to avoid doing a FindSectionByName for each symbol. The "const
+ // char*" key must
+ // came from a ConstString object so they can be compared by pointer
+ std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
+
+ unsigned i;
+ for (i = 0; i < num_symbols; ++i) {
+ if (symbol.Parse(symtab_data, &offset) == false)
+ break;
- const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
- if (!symbol_name)
- symbol_name = "";
-
- // No need to add non-section symbols that have no names
- if (symbol.getType() != STT_SECTION &&
- (symbol_name == nullptr || symbol_name[0] == '\0'))
- continue;
+ const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+ if (!symbol_name)
+ symbol_name = "";
- // Skipping oatdata and oatexec sections if it is requested. See details above the
- // definition of skip_oatdata_oatexec for the reasons.
- if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 || ::strcmp(symbol_name, "oatexec") == 0))
- continue;
+ // No need to add non-section symbols that have no names
+ if (symbol.getType() != STT_SECTION &&
+ (symbol_name == nullptr || symbol_name[0] == '\0'))
+ continue;
+
+ // Skipping oatdata and oatexec sections if it is requested. See details
+ // above the
+ // definition of skip_oatdata_oatexec for the reasons.
+ if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 ||
+ ::strcmp(symbol_name, "oatexec") == 0))
+ continue;
+
+ SectionSP symbol_section_sp;
+ SymbolType symbol_type = eSymbolTypeInvalid;
+ Elf64_Half section_idx = symbol.st_shndx;
+
+ switch (section_idx) {
+ case SHN_ABS:
+ symbol_type = eSymbolTypeAbsolute;
+ break;
+ case SHN_UNDEF:
+ symbol_type = eSymbolTypeUndefined;
+ break;
+ default:
+ symbol_section_sp = section_list->GetSectionAtIndex(section_idx);
+ break;
+ }
- SectionSP symbol_section_sp;
- SymbolType symbol_type = eSymbolTypeInvalid;
- Elf64_Half section_idx = symbol.st_shndx;
-
- switch (section_idx)
- {
- case SHN_ABS:
- symbol_type = eSymbolTypeAbsolute;
- break;
- case SHN_UNDEF:
- symbol_type = eSymbolTypeUndefined;
- break;
- default:
- symbol_section_sp = section_list->GetSectionAtIndex(section_idx);
- break;
- }
+ // If a symbol is undefined do not process it further even if it has a STT
+ // type
+ if (symbol_type != eSymbolTypeUndefined) {
+ switch (symbol.getType()) {
+ default:
+ case STT_NOTYPE:
+ // The symbol's type is not specified.
+ break;
- // If a symbol is undefined do not process it further even if it has a STT type
- if (symbol_type != eSymbolTypeUndefined)
- {
- switch (symbol.getType())
- {
- default:
- case STT_NOTYPE:
- // The symbol's type is not specified.
- break;
+ case STT_OBJECT:
+ // The symbol is associated with a data object, such as a variable,
+ // an array, etc.
+ symbol_type = eSymbolTypeData;
+ break;
- case STT_OBJECT:
- // The symbol is associated with a data object, such as a variable,
- // an array, etc.
- symbol_type = eSymbolTypeData;
- break;
+ case STT_FUNC:
+ // The symbol is associated with a function or other executable code.
+ symbol_type = eSymbolTypeCode;
+ break;
- case STT_FUNC:
- // The symbol is associated with a function or other executable code.
- symbol_type = eSymbolTypeCode;
- break;
+ case STT_SECTION:
+ // The symbol is associated with a section. Symbol table entries of
+ // this type exist primarily for relocation and normally have
+ // STB_LOCAL binding.
+ break;
- case STT_SECTION:
- // The symbol is associated with a section. Symbol table entries of
- // this type exist primarily for relocation and normally have
- // STB_LOCAL binding.
- break;
+ case STT_FILE:
+ // Conventionally, the symbol's name gives the name of the source
+ // file associated with the object file. A file symbol has STB_LOCAL
+ // binding, its section index is SHN_ABS, and it precedes the other
+ // STB_LOCAL symbols for the file, if it is present.
+ symbol_type = eSymbolTypeSourceFile;
+ break;
- case STT_FILE:
- // Conventionally, the symbol's name gives the name of the source
- // file associated with the object file. A file symbol has STB_LOCAL
- // binding, its section index is SHN_ABS, and it precedes the other
- // STB_LOCAL symbols for the file, if it is present.
- symbol_type = eSymbolTypeSourceFile;
- break;
+ case STT_GNU_IFUNC:
+ // The symbol is associated with an indirect function. The actual
+ // function will be resolved if it is referenced.
+ symbol_type = eSymbolTypeResolver;
+ break;
+ }
+ }
- case STT_GNU_IFUNC:
- // The symbol is associated with an indirect function. The actual
- // function will be resolved if it is referenced.
- symbol_type = eSymbolTypeResolver;
- break;
+ if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION) {
+ if (symbol_section_sp) {
+ const ConstString §_name = symbol_section_sp->GetName();
+ if (sect_name == text_section_name || sect_name == init_section_name ||
+ sect_name == fini_section_name || sect_name == ctors_section_name ||
+ sect_name == dtors_section_name) {
+ symbol_type = eSymbolTypeCode;
+ } else if (sect_name == data_section_name ||
+ sect_name == data2_section_name ||
+ sect_name == rodata_section_name ||
+ sect_name == rodata1_section_name ||
+ sect_name == bss_section_name) {
+ symbol_type = eSymbolTypeData;
+ }
+ }
+ }
+
+ int64_t symbol_value_offset = 0;
+ uint32_t additional_flags = 0;
+
+ if (arch.IsValid()) {
+ if (arch.GetMachine() == llvm::Triple::arm) {
+ if (symbol.getBinding() == STB_LOCAL) {
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
+ if (symbol_type == eSymbolTypeCode) {
+ switch (mapping_symbol) {
+ case 'a':
+ // $a[.<any>]* - marks an ARM instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'b':
+ case 't':
+ // $b[.<any>]* - marks a THUMB BL instruction sequence
+ // $t[.<any>]* - marks a THUMB instruction sequence
+ m_address_class_map[symbol.st_value] =
+ eAddressClassCodeAlternateISA;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
+ }
+ if (mapping_symbol)
+ continue;
}
-
- if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION)
- {
- if (symbol_section_sp)
- {
- const ConstString §_name = symbol_section_sp->GetName();
- if (sect_name == text_section_name ||
- sect_name == init_section_name ||
- sect_name == fini_section_name ||
- sect_name == ctors_section_name ||
- sect_name == dtors_section_name)
- {
- symbol_type = eSymbolTypeCode;
- }
- else if (sect_name == data_section_name ||
- sect_name == data2_section_name ||
- sect_name == rodata_section_name ||
- sect_name == rodata1_section_name ||
- sect_name == bss_section_name)
- {
- symbol_type = eSymbolTypeData;
- }
+ } else if (arch.GetMachine() == llvm::Triple::aarch64) {
+ if (symbol.getBinding() == STB_LOCAL) {
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
+ if (symbol_type == eSymbolTypeCode) {
+ switch (mapping_symbol) {
+ case 'x':
+ // $x[.<any>]* - marks an A64 instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
+ }
+ if (mapping_symbol)
+ continue;
}
+ }
- int64_t symbol_value_offset = 0;
- uint32_t additional_flags = 0;
-
- if (arch.IsValid())
- {
- if (arch.GetMachine() == llvm::Triple::arm)
- {
- if (symbol.getBinding() == STB_LOCAL)
- {
- char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
- if (symbol_type == eSymbolTypeCode)
- {
- switch (mapping_symbol)
- {
- case 'a':
- // $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- break;
- case 'b':
- case 't':
- // $b[.<any>]* - marks a THUMB BL instruction sequence
- // $t[.<any>]* - marks a THUMB instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
- break;
- case 'd':
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
- break;
- }
- }
- if (mapping_symbol)
- continue;
- }
- }
- else if (arch.GetMachine() == llvm::Triple::aarch64)
- {
- if (symbol.getBinding() == STB_LOCAL)
- {
- char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
- if (symbol_type == eSymbolTypeCode)
- {
- switch (mapping_symbol)
- {
- case 'x':
- // $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- break;
- case 'd':
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
- break;
- }
- }
- if (mapping_symbol)
- continue;
- }
- }
+ if (arch.GetMachine() == llvm::Triple::arm) {
+ if (symbol_type == eSymbolTypeCode) {
+ if (symbol.st_value & 1) {
+ // Subtracting 1 from the address effectively unsets
+ // the low order bit, which results in the address
+ // actually pointing to the beginning of the symbol.
+ // This delta will be used below in conjunction with
+ // symbol.st_value to produce the final symbol_value
+ // that we store in the symtab.
+ symbol_value_offset = -1;
+ m_address_class_map[symbol.st_value ^ 1] =
+ eAddressClassCodeAlternateISA;
+ } else {
+ // This address is ARM
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ }
+ }
+ }
+
+ /*
+ * MIPS:
+ * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for
+ * MIPS).
+ * This allows processor to switch between microMIPS and MIPS without any
+ * need
+ * for special mode-control register. However, apart from .debug_line,
+ * none of
+ * the ELF/DWARF sections set the ISA bit (for symbol or section). Use
+ * st_other
+ * flag to check whether the symbol is microMIPS and then set the address
+ * class
+ * accordingly.
+ */
+ const llvm::Triple::ArchType llvm_arch = arch.GetMachine();
+ if (llvm_arch == llvm::Triple::mips ||
+ llvm_arch == llvm::Triple::mipsel ||
+ llvm_arch == llvm::Triple::mips64 ||
+ llvm_arch == llvm::Triple::mips64el) {
+ if (IS_MICROMIPS(symbol.st_other))
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
+ symbol.st_value = symbol.st_value & (~1ull);
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ } else {
+ if (symbol_type == eSymbolTypeCode)
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ else if (symbol_type == eSymbolTypeData)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ else
+ m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ }
+ }
+ }
+
+ // symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB
+ // symbols. See above for
+ // more details.
+ uint64_t symbol_value = symbol.st_value + symbol_value_offset;
+
+ if (symbol_section_sp == nullptr && section_idx == SHN_ABS &&
+ symbol.st_size != 0) {
+ // We don't have a section for a symbol with non-zero size. Create a new
+ // section for it
+ // so the address range covered by the symbol is also covered by the
+ // module (represented
+ // through the section list). It is needed so module lookup for the
+ // addresses covered
+ // by this symbol will be successfull. This case happens for absolute
+ // symbols.
+ ConstString fake_section_name(std::string(".absolute.") + symbol_name);
+ symbol_section_sp =
+ std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name,
+ eSectionTypeAbsoluteAddress, symbol_value,
+ symbol.st_size, 0, 0, 0, SHF_ALLOC);
+
+ module_section_list->AddSection(symbol_section_sp);
+ section_list->AddSection(symbol_section_sp);
+ }
+
+ if (symbol_section_sp &&
+ CalculateType() != ObjectFile::Type::eTypeObjectFile)
+ symbol_value -= symbol_section_sp->GetFileAddress();
+
+ if (symbol_section_sp && module_section_list &&
+ module_section_list != section_list) {
+ const ConstString §_name = symbol_section_sp->GetName();
+ auto section_it = section_name_to_section.find(sect_name.GetCString());
+ if (section_it == section_name_to_section.end())
+ section_it =
+ section_name_to_section
+ .emplace(sect_name.GetCString(),
+ module_section_list->FindSectionByName(sect_name))
+ .first;
+ if (section_it->second && section_it->second->GetFileSize())
+ symbol_section_sp = section_it->second;
+ }
+
+ bool is_global = symbol.getBinding() == STB_GLOBAL;
+ uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;
+ bool is_mangled = (symbol_name[0] == '_' && symbol_name[1] == 'Z');
+
+ llvm::StringRef symbol_ref(symbol_name);
+
+ // Symbol names may contain @VERSION suffixes. Find those and strip them
+ // temporarily.
+ size_t version_pos = symbol_ref.find('@');
+ bool has_suffix = version_pos != llvm::StringRef::npos;
+ llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos);
+ Mangled mangled(ConstString(symbol_bare), is_mangled);
+
+ // Now append the suffix back to mangled and unmangled names. Only do it if
+ // the
+ // demangling was successful (string is not empty).
+ if (has_suffix) {
+ llvm::StringRef suffix = symbol_ref.substr(version_pos);
+
+ llvm::StringRef mangled_name = mangled.GetMangledName().GetStringRef();
+ if (!mangled_name.empty())
+ mangled.SetMangledName(ConstString((mangled_name + suffix).str()));
+
+ ConstString demangled =
+ mangled.GetDemangledName(lldb::eLanguageTypeUnknown);
+ llvm::StringRef demangled_name = demangled.GetStringRef();
+ if (!demangled_name.empty())
+ mangled.SetDemangledName(ConstString((demangled_name + suffix).str()));
+ }
+
+ // In ELF all symbol should have a valid size but it is not true for some
+ // function symbols
+ // coming from hand written assembly. As none of the function symbol should
+ // have 0 size we
+ // try to calculate the size for these symbols in the symtab with saying
+ // that their original
+ // size is not valid.
+ bool symbol_size_valid =
+ symbol.st_size != 0 || symbol.getType() != STT_FUNC;
+
+ Symbol dc_symbol(
+ i + start_id, // ID is the original symbol table index.
+ mangled,
+ symbol_type, // Type of this symbol
+ is_global, // Is this globally visible?
+ false, // Is this symbol debug info?
+ false, // Is this symbol a trampoline?
+ false, // Is this symbol artificial?
+ AddressRange(symbol_section_sp, // Section in which this symbol is
+ // defined or null.
+ symbol_value, // Offset in section or symbol value.
+ symbol.st_size), // Size in bytes of this symbol.
+ symbol_size_valid, // Symbol size is valid
+ has_suffix, // Contains linker annotations?
+ flags); // Symbol flags.
+ symtab->AddSymbol(dc_symbol);
+ }
+ return i;
+}
+
+unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
+ user_id_t start_id,
+ lldb_private::Section *symtab) {
+ if (symtab->GetObjectFile() != this) {
+ // If the symbol table section is owned by a different object file, have it
+ // do the
+ // parsing.
+ ObjectFileELF *obj_file_elf =
+ static_cast<ObjectFileELF *>(symtab->GetObjectFile());
+ return obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
+ }
+
+ // Get section list for this object file.
+ SectionList *section_list = m_sections_ap.get();
+ if (!section_list)
+ return 0;
- if (arch.GetMachine() == llvm::Triple::arm)
- {
- if (symbol_type == eSymbolTypeCode)
- {
- if (symbol.st_value & 1)
- {
- // Subtracting 1 from the address effectively unsets
- // the low order bit, which results in the address
- // actually pointing to the beginning of the symbol.
- // This delta will be used below in conjunction with
- // symbol.st_value to produce the final symbol_value
- // that we store in the symtab.
- symbol_value_offset = -1;
- m_address_class_map[symbol.st_value^1] = eAddressClassCodeAlternateISA;
- }
- else
- {
- // This address is ARM
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- }
- }
- }
+ user_id_t symtab_id = symtab->GetID();
+ const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
+ assert(symtab_hdr->sh_type == SHT_SYMTAB ||
+ symtab_hdr->sh_type == SHT_DYNSYM);
+
+ // sh_link: section header index of associated string table.
+ // Section ID's are ones based.
+ user_id_t strtab_id = symtab_hdr->sh_link + 1;
+ Section *strtab = section_list->FindSectionByID(strtab_id).get();
+
+ if (symtab && strtab) {
+ assert(symtab->GetObjectFile() == this);
+ assert(strtab->GetObjectFile() == this);
- /*
- * MIPS:
- * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS).
- * This allows processor to switch between microMIPS and MIPS without any need
- * for special mode-control register. However, apart from .debug_line, none of
- * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other
- * flag to check whether the symbol is microMIPS and then set the address class
- * accordingly.
- */
- const llvm::Triple::ArchType llvm_arch = arch.GetMachine();
- if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel
- || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el)
- {
- if (IS_MICROMIPS(symbol.st_other))
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
- else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode))
- {
- symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
- }
- else
- {
- if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = eAddressClassData;
- else
- m_address_class_map[symbol.st_value] = eAddressClassUnknown;
- }
- }
- }
+ DataExtractor symtab_data;
+ DataExtractor strtab_data;
+ if (ReadSectionData(symtab, symtab_data) &&
+ ReadSectionData(strtab, strtab_data)) {
+ size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;
- // symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB symbols. See above for
- // more details.
- uint64_t symbol_value = symbol.st_value + symbol_value_offset;
-
- if (symbol_section_sp == nullptr && section_idx == SHN_ABS && symbol.st_size != 0)
- {
- // We don't have a section for a symbol with non-zero size. Create a new section for it
- // so the address range covered by the symbol is also covered by the module (represented
- // through the section list). It is needed so module lookup for the addresses covered
- // by this symbol will be successfull. This case happens for absolute symbols.
- ConstString fake_section_name(std::string(".absolute.") + symbol_name);
- symbol_section_sp = std::make_shared<Section>(module_sp,
- this,
- SHN_ABS,
- fake_section_name,
- eSectionTypeAbsoluteAddress,
- symbol_value,
- symbol.st_size,
- 0, 0, 0,
- SHF_ALLOC);
-
- module_section_list->AddSection(symbol_section_sp);
- section_list->AddSection(symbol_section_sp);
- }
-
- if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
- symbol_value -= symbol_section_sp->GetFileAddress();
-
- if (symbol_section_sp && module_section_list && module_section_list != section_list)
- {
- const ConstString §_name = symbol_section_sp->GetName();
- auto section_it = section_name_to_section.find(sect_name.GetCString());
- if (section_it == section_name_to_section.end())
- section_it = section_name_to_section.emplace(
- sect_name.GetCString(),
- module_section_list->FindSectionByName (sect_name)).first;
- if (section_it->second && section_it->second->GetFileSize())
- symbol_section_sp = section_it->second;
- }
-
- bool is_global = symbol.getBinding() == STB_GLOBAL;
- uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;
- bool is_mangled = (symbol_name[0] == '_' && symbol_name[1] == 'Z');
-
- llvm::StringRef symbol_ref(symbol_name);
-
- // Symbol names may contain @VERSION suffixes. Find those and strip them temporarily.
- size_t version_pos = symbol_ref.find('@');
- bool has_suffix = version_pos != llvm::StringRef::npos;
- llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos);
- Mangled mangled(ConstString(symbol_bare), is_mangled);
-
- // Now append the suffix back to mangled and unmangled names. Only do it if the
- // demangling was successful (string is not empty).
- if (has_suffix)
- {
- llvm::StringRef suffix = symbol_ref.substr(version_pos);
-
- llvm::StringRef mangled_name = mangled.GetMangledName().GetStringRef();
- if (! mangled_name.empty())
- mangled.SetMangledName( ConstString((mangled_name + suffix).str()) );
-
- ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeUnknown);
- llvm::StringRef demangled_name = demangled.GetStringRef();
- if (!demangled_name.empty())
- mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) );
- }
-
- // In ELF all symbol should have a valid size but it is not true for some function symbols
- // coming from hand written assembly. As none of the function symbol should have 0 size we
- // try to calculate the size for these symbols in the symtab with saying that their original
- // size is not valid.
- bool symbol_size_valid = symbol.st_size != 0 || symbol.getType() != STT_FUNC;
-
- Symbol dc_symbol(
- i + start_id, // ID is the original symbol table index.
- mangled,
- symbol_type, // Type of this symbol
- is_global, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- false, // Is this symbol artificial?
- AddressRange(
- symbol_section_sp, // Section in which this symbol is defined or null.
- symbol_value, // Offset in section or symbol value.
- symbol.st_size), // Size in bytes of this symbol.
- symbol_size_valid, // Symbol size is valid
- has_suffix, // Contains linker annotations?
- flags); // Symbol flags.
- symtab->AddSymbol(dc_symbol);
+ return ParseSymbols(symbol_table, start_id, section_list, num_symbols,
+ symtab_data, strtab_data);
}
- return i;
-}
+ }
-unsigned
-ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
- user_id_t start_id,
- lldb_private::Section *symtab)
-{
- if (symtab->GetObjectFile() != this)
- {
- // If the symbol table section is owned by a different object file, have it do the
- // parsing.
- ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(symtab->GetObjectFile());
- return obj_file_elf->ParseSymbolTable (symbol_table, start_id, symtab);
- }
+ return 0;
+}
- // Get section list for this object file.
- SectionList *section_list = m_sections_ap.get();
- if (!section_list)
- return 0;
+size_t ObjectFileELF::ParseDynamicSymbols() {
+ if (m_dynamic_symbols.size())
+ return m_dynamic_symbols.size();
- user_id_t symtab_id = symtab->GetID();
- const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
- assert(symtab_hdr->sh_type == SHT_SYMTAB ||
- symtab_hdr->sh_type == SHT_DYNSYM);
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return 0;
- // sh_link: section header index of associated string table.
- // Section ID's are ones based.
- user_id_t strtab_id = symtab_hdr->sh_link + 1;
- Section *strtab = section_list->FindSectionByID(strtab_id).get();
+ // Find the SHT_DYNAMIC section.
+ Section *dynsym =
+ section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)
+ .get();
+ if (!dynsym)
+ return 0;
+ assert(dynsym->GetObjectFile() == this);
- if (symtab && strtab)
- {
- assert (symtab->GetObjectFile() == this);
- assert (strtab->GetObjectFile() == this);
+ ELFDynamic symbol;
+ DataExtractor dynsym_data;
+ if (ReadSectionData(dynsym, dynsym_data)) {
+ const lldb::offset_t section_size = dynsym_data.GetByteSize();
+ lldb::offset_t cursor = 0;
- DataExtractor symtab_data;
- DataExtractor strtab_data;
- if (ReadSectionData(symtab, symtab_data) &&
- ReadSectionData(strtab, strtab_data))
- {
- size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;
+ while (cursor < section_size) {
+ if (!symbol.Parse(dynsym_data, &cursor))
+ break;
- return ParseSymbols(symbol_table, start_id, section_list,
- num_symbols, symtab_data, strtab_data);
- }
+ m_dynamic_symbols.push_back(symbol);
}
+ }
- return 0;
+ return m_dynamic_symbols.size();
}
-size_t
-ObjectFileELF::ParseDynamicSymbols()
-{
- if (m_dynamic_symbols.size())
- return m_dynamic_symbols.size();
-
- SectionList *section_list = GetSectionList();
- if (!section_list)
- return 0;
-
- // Find the SHT_DYNAMIC section.
- Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
- if (!dynsym)
- return 0;
- assert (dynsym->GetObjectFile() == this);
+const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) {
+ if (!ParseDynamicSymbols())
+ return NULL;
- ELFDynamic symbol;
- DataExtractor dynsym_data;
- if (ReadSectionData(dynsym, dynsym_data))
- {
- const lldb::offset_t section_size = dynsym_data.GetByteSize();
- lldb::offset_t cursor = 0;
-
- while (cursor < section_size)
- {
- if (!symbol.Parse(dynsym_data, &cursor))
- break;
+ DynamicSymbolCollIter I = m_dynamic_symbols.begin();
+ DynamicSymbolCollIter E = m_dynamic_symbols.end();
+ for (; I != E; ++I) {
+ ELFDynamic *symbol = &*I;
- m_dynamic_symbols.push_back(symbol);
- }
- }
+ if (symbol->d_tag == tag)
+ return symbol;
+ }
- return m_dynamic_symbols.size();
+ return NULL;
}
-const ELFDynamic *
-ObjectFileELF::FindDynamicSymbol(unsigned tag)
-{
- if (!ParseDynamicSymbols())
- return NULL;
-
- DynamicSymbolCollIter I = m_dynamic_symbols.begin();
- DynamicSymbolCollIter E = m_dynamic_symbols.end();
- for ( ; I != E; ++I)
- {
- ELFDynamic *symbol = &*I;
+unsigned ObjectFileELF::PLTRelocationType() {
+ // DT_PLTREL
+ // This member specifies the type of relocation entry to which the
+ // procedure linkage table refers. The d_val member holds DT_REL or
+ // DT_RELA, as appropriate. All relocations in a procedure linkage table
+ // must use the same relocation.
+ const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);
- if (symbol->d_tag == tag)
- return symbol;
- }
+ if (symbol)
+ return symbol->d_val;
- return NULL;
+ return 0;
}
-unsigned
-ObjectFileELF::PLTRelocationType()
-{
- // DT_PLTREL
- // This member specifies the type of relocation entry to which the
- // procedure linkage table refers. The d_val member holds DT_REL or
- // DT_RELA, as appropriate. All relocations in a procedure linkage table
- // must use the same relocation.
- const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);
+// Returns the size of the normal plt entries and the offset of the first normal
+// plt entry. The
+// 0th entry in the plt table is usually a resolution entry which have different
+// size in some
+// architectures then the rest of the plt entries.
+static std::pair<uint64_t, uint64_t>
+GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
+ const ELFSectionHeader *plt_hdr) {
+ const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16
+ // bytes.
+ // So round the entsize up by the alignment if addralign is set.
+ elf_xword plt_entsize =
+ plt_hdr->sh_addralign
+ ? llvm::alignTo(plt_hdr->sh_entsize, plt_hdr->sh_addralign)
+ : plt_hdr->sh_entsize;
+
+ // Some linkers e.g ld for arm, fill plt_hdr->sh_entsize field incorrectly.
+ // PLT entries relocation code in general requires multiple instruction and
+ // should be greater than 4 bytes in most cases. Try to guess correct size
+ // just in case.
+ if (plt_entsize <= 4) {
+ // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the
+ // size of the plt
+ // entries based on the number of entries and the size of the plt section
+ // with the
+ // assumption that the size of the 0th entry is at least as big as the size
+ // of the normal
+ // entries and it isn't much bigger then that.
+ if (plt_hdr->sh_addralign)
+ plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign /
+ (num_relocations + 1) * plt_hdr->sh_addralign;
+ else
+ plt_entsize = plt_hdr->sh_size / (num_relocations + 1);
+ }
- if (symbol)
- return symbol->d_val;
+ elf_xword plt_offset = plt_hdr->sh_size - num_relocations * plt_entsize;
- return 0;
+ return std::make_pair(plt_entsize, plt_offset);
}
-// Returns the size of the normal plt entries and the offset of the first normal plt entry. The
-// 0th entry in the plt table is usually a resolution entry which have different size in some
-// architectures then the rest of the plt entries.
-static std::pair<uint64_t, uint64_t>
-GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr)
-{
- const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
-
- // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes.
- // So round the entsize up by the alignment if addralign is set.
- elf_xword plt_entsize = plt_hdr->sh_addralign ?
- llvm::alignTo (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize;
-
- // Some linkers e.g ld for arm, fill plt_hdr->sh_entsize field incorrectly.
- // PLT entries relocation code in general requires multiple instruction and
- // should be greater than 4 bytes in most cases. Try to guess correct size just in case.
- if (plt_entsize <= 4)
- {
- // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt
- // entries based on the number of entries and the size of the plt section with the
- // assumption that the size of the 0th entry is at least as big as the size of the normal
- // entries and it isn't much bigger then that.
- if (plt_hdr->sh_addralign)
- plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign;
- else
- plt_entsize = plt_hdr->sh_size / (num_relocations + 1);
- }
+static unsigned ParsePLTRelocations(
+ Symtab *symbol_table, user_id_t start_id, unsigned rel_type,
+ const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
+ const ELFSectionHeader *plt_hdr, const ELFSectionHeader *sym_hdr,
+ const lldb::SectionSP &plt_section_sp, DataExtractor &rel_data,
+ DataExtractor &symtab_data, DataExtractor &strtab_data) {
+ ELFRelocation rel(rel_type);
+ ELFSymbol symbol;
+ lldb::offset_t offset = 0;
+
+ uint64_t plt_offset, plt_entsize;
+ std::tie(plt_entsize, plt_offset) =
+ GetPltEntrySizeAndOffset(rel_hdr, plt_hdr);
+ const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+
+ typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
+ reloc_info_fn reloc_type;
+ reloc_info_fn reloc_symbol;
+
+ if (hdr->Is32Bit()) {
+ reloc_type = ELFRelocation::RelocType32;
+ reloc_symbol = ELFRelocation::RelocSymbol32;
+ } else {
+ reloc_type = ELFRelocation::RelocType64;
+ reloc_symbol = ELFRelocation::RelocSymbol64;
+ }
+
+ unsigned slot_type = hdr->GetRelocationJumpSlotType();
+ unsigned i;
+ for (i = 0; i < num_relocations; ++i) {
+ if (rel.Parse(rel_data, &offset) == false)
+ break;
+
+ if (reloc_type(rel) != slot_type)
+ continue;
+
+ lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
+ if (!symbol.Parse(symtab_data, &symbol_offset))
+ break;
+
+ const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+ bool is_mangled =
+ symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
+ uint64_t plt_index = plt_offset + i * plt_entsize;
+
+ Symbol jump_symbol(
+ i + start_id, // Symbol table index
+ symbol_name, // symbol name.
+ is_mangled, // is the symbol name mangled?
+ eSymbolTypeTrampoline, // Type of this symbol
+ false, // Is this globally visible?
+ false, // Is this symbol debug info?
+ true, // Is this symbol a trampoline?
+ true, // Is this symbol artificial?
+ plt_section_sp, // Section in which this symbol is defined or null.
+ plt_index, // Offset in section or symbol value.
+ plt_entsize, // Size in bytes of this symbol.
+ true, // Size is valid
+ false, // Contains linker annotations?
+ 0); // Symbol flags.
- elf_xword plt_offset = plt_hdr->sh_size - num_relocations * plt_entsize;
+ symbol_table->AddSymbol(jump_symbol);
+ }
- return std::make_pair(plt_entsize, plt_offset);
+ return i;
}
-static unsigned
-ParsePLTRelocations(Symtab *symbol_table,
- user_id_t start_id,
- unsigned rel_type,
- const ELFHeader *hdr,
- const ELFSectionHeader *rel_hdr,
- const ELFSectionHeader *plt_hdr,
- const ELFSectionHeader *sym_hdr,
- const lldb::SectionSP &plt_section_sp,
- DataExtractor &rel_data,
- DataExtractor &symtab_data,
- DataExtractor &strtab_data)
-{
- ELFRelocation rel(rel_type);
- ELFSymbol symbol;
- lldb::offset_t offset = 0;
-
- uint64_t plt_offset, plt_entsize;
- std::tie(plt_entsize, plt_offset) = GetPltEntrySizeAndOffset(rel_hdr, plt_hdr);
- const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
-
- typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
- reloc_info_fn reloc_type;
- reloc_info_fn reloc_symbol;
-
- if (hdr->Is32Bit())
- {
- reloc_type = ELFRelocation::RelocType32;
- reloc_symbol = ELFRelocation::RelocSymbol32;
- }
- else
- {
- reloc_type = ELFRelocation::RelocType64;
- reloc_symbol = ELFRelocation::RelocSymbol64;
- }
+unsigned
+ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
+ const ELFSectionHeaderInfo *rel_hdr,
+ user_id_t rel_id) {
+ assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
- unsigned slot_type = hdr->GetRelocationJumpSlotType();
- unsigned i;
- for (i = 0; i < num_relocations; ++i)
- {
- if (rel.Parse(rel_data, &offset) == false)
- break;
+ // The link field points to the associated symbol table.
+ user_id_t symtab_id = rel_hdr->sh_link;
- if (reloc_type(rel) != slot_type)
- continue;
+ // If the link field doesn't point to the appropriate symbol name table then
+ // try to find it by name as some compiler don't fill in the link fields.
+ if (!symtab_id)
+ symtab_id = GetSectionIndexByName(".dynsym");
+
+ // Get PLT section. We cannot use rel_hdr->sh_info, since current linkers
+ // point that to the .got.plt or .got section instead of .plt.
+ user_id_t plt_id = GetSectionIndexByName(".plt");
- lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
- if (!symbol.Parse(symtab_data, &symbol_offset))
- break;
+ if (!symtab_id || !plt_id)
+ return 0;
- const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
- bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
- uint64_t plt_index = plt_offset + i * plt_entsize;
-
- Symbol jump_symbol(
- i + start_id, // Symbol table index
- symbol_name, // symbol name.
- is_mangled, // is the symbol name mangled?
- eSymbolTypeTrampoline, // Type of this symbol
- false, // Is this globally visible?
- false, // Is this symbol debug info?
- true, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- plt_section_sp, // Section in which this symbol is defined or null.
- plt_index, // Offset in section or symbol value.
- plt_entsize, // Size in bytes of this symbol.
- true, // Size is valid
- false, // Contains linker annotations?
- 0); // Symbol flags.
+ // Section ID's are ones based;
+ symtab_id++;
+ plt_id++;
- symbol_table->AddSymbol(jump_symbol);
- }
+ const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
+ if (!plt_hdr)
+ return 0;
- return i;
-}
+ const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id);
+ if (!sym_hdr)
+ return 0;
-unsigned
-ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
- user_id_t start_id,
- const ELFSectionHeaderInfo *rel_hdr,
- user_id_t rel_id)
-{
- assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
-
- // The link field points to the associated symbol table.
- user_id_t symtab_id = rel_hdr->sh_link;
-
- // If the link field doesn't point to the appropriate symbol name table then
- // try to find it by name as some compiler don't fill in the link fields.
- if (!symtab_id)
- symtab_id = GetSectionIndexByName(".dynsym");
-
- // Get PLT section. We cannot use rel_hdr->sh_info, since current linkers
- // point that to the .got.plt or .got section instead of .plt.
- user_id_t plt_id = GetSectionIndexByName(".plt");
-
- if (!symtab_id || !plt_id)
- return 0;
-
- // Section ID's are ones based;
- symtab_id++;
- plt_id++;
-
- const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
- if (!plt_hdr)
- return 0;
-
- const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id);
- if (!sym_hdr)
- return 0;
+ SectionList *section_list = m_sections_ap.get();
+ if (!section_list)
+ return 0;
- SectionList *section_list = m_sections_ap.get();
- if (!section_list)
- return 0;
+ Section *rel_section = section_list->FindSectionByID(rel_id).get();
+ if (!rel_section)
+ return 0;
- Section *rel_section = section_list->FindSectionByID(rel_id).get();
- if (!rel_section)
- return 0;
-
- SectionSP plt_section_sp (section_list->FindSectionByID(plt_id));
- if (!plt_section_sp)
- return 0;
-
- Section *symtab = section_list->FindSectionByID(symtab_id).get();
- if (!symtab)
- return 0;
-
- // sh_link points to associated string table.
- Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
- if (!strtab)
- return 0;
-
- DataExtractor rel_data;
- if (!ReadSectionData(rel_section, rel_data))
- return 0;
+ SectionSP plt_section_sp(section_list->FindSectionByID(plt_id));
+ if (!plt_section_sp)
+ return 0;
- DataExtractor symtab_data;
- if (!ReadSectionData(symtab, symtab_data))
- return 0;
+ Section *symtab = section_list->FindSectionByID(symtab_id).get();
+ if (!symtab)
+ return 0;
- DataExtractor strtab_data;
- if (!ReadSectionData(strtab, strtab_data))
- return 0;
+ // sh_link points to associated string table.
+ Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
+ if (!strtab)
+ return 0;
- unsigned rel_type = PLTRelocationType();
- if (!rel_type)
- return 0;
-
- return ParsePLTRelocations (symbol_table,
- start_id,
- rel_type,
- &m_header,
- rel_hdr,
- plt_hdr,
- sym_hdr,
- plt_section_sp,
- rel_data,
- symtab_data,
- strtab_data);
-}
+ DataExtractor rel_data;
+ if (!ReadSectionData(rel_section, rel_data))
+ return 0;
-unsigned
-ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
- const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
- DataExtractor &rel_data, DataExtractor &symtab_data,
- DataExtractor &debug_data, Section* rel_section)
-{
- ELFRelocation rel(rel_hdr->sh_type);
- lldb::addr_t offset = 0;
- const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
- typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
- reloc_info_fn reloc_type;
- reloc_info_fn reloc_symbol;
-
- if (hdr->Is32Bit())
- {
- reloc_type = ELFRelocation::RelocType32;
- reloc_symbol = ELFRelocation::RelocSymbol32;
- }
- else
- {
- reloc_type = ELFRelocation::RelocType64;
- reloc_symbol = ELFRelocation::RelocSymbol64;
- }
+ DataExtractor symtab_data;
+ if (!ReadSectionData(symtab, symtab_data))
+ return 0;
- for (unsigned i = 0; i < num_relocations; ++i)
- {
- if (rel.Parse(rel_data, &offset) == false)
- break;
+ DataExtractor strtab_data;
+ if (!ReadSectionData(strtab, strtab_data))
+ return 0;
- Symbol* symbol = NULL;
+ unsigned rel_type = PLTRelocationType();
+ if (!rel_type)
+ return 0;
- if (hdr->Is32Bit())
- {
- switch (reloc_type(rel)) {
- case R_386_32:
- case R_386_PC32:
- default:
- assert(false && "unexpected relocation type");
- }
- } else {
- switch (reloc_type(rel)) {
- case R_X86_64_64:
- {
- symbol = symtab->FindSymbolByID(reloc_symbol(rel));
- if (symbol)
- {
- addr_t value = symbol->GetAddressRef().GetFileAddress();
- DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
- uint64_t* dst = reinterpret_cast<uint64_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset64(rel));
- *dst = value + ELFRelocation::RelocAddend64(rel);
- }
- break;
- }
- case R_X86_64_32:
- case R_X86_64_32S:
- {
- symbol = symtab->FindSymbolByID(reloc_symbol(rel));
- if (symbol)
- {
- addr_t value = symbol->GetAddressRef().GetFileAddress();
- value += ELFRelocation::RelocAddend32(rel);
- assert((reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
- (reloc_type(rel) == R_X86_64_32S &&
- ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
- uint32_t truncated_addr = (value & 0xFFFFFFFF);
- DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();
- uint32_t* dst = reinterpret_cast<uint32_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel));
- *dst = truncated_addr;
- }
- break;
- }
- case R_X86_64_PC32:
- default:
- assert(false && "unexpected relocation type");
- }
+ return ParsePLTRelocations(symbol_table, start_id, rel_type, &m_header,
+ rel_hdr, plt_hdr, sym_hdr, plt_section_sp,
+ rel_data, symtab_data, strtab_data);
+}
+
+unsigned ObjectFileELF::RelocateSection(
+ Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
+ const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
+ DataExtractor &rel_data, DataExtractor &symtab_data,
+ DataExtractor &debug_data, Section *rel_section) {
+ ELFRelocation rel(rel_hdr->sh_type);
+ lldb::addr_t offset = 0;
+ const unsigned num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+ typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
+ reloc_info_fn reloc_type;
+ reloc_info_fn reloc_symbol;
+
+ if (hdr->Is32Bit()) {
+ reloc_type = ELFRelocation::RelocType32;
+ reloc_symbol = ELFRelocation::RelocSymbol32;
+ } else {
+ reloc_type = ELFRelocation::RelocType64;
+ reloc_symbol = ELFRelocation::RelocSymbol64;
+ }
+
+ for (unsigned i = 0; i < num_relocations; ++i) {
+ if (rel.Parse(rel_data, &offset) == false)
+ break;
+
+ Symbol *symbol = NULL;
+
+ if (hdr->Is32Bit()) {
+ switch (reloc_type(rel)) {
+ case R_386_32:
+ case R_386_PC32:
+ default:
+ assert(false && "unexpected relocation type");
+ }
+ } else {
+ switch (reloc_type(rel)) {
+ case R_X86_64_64: {
+ symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+ if (symbol) {
+ addr_t value = symbol->GetAddressRef().GetFileAddress();
+ DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+ uint64_t *dst = reinterpret_cast<uint64_t *>(
+ data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
+ ELFRelocation::RelocOffset64(rel));
+ *dst = value + ELFRelocation::RelocAddend64(rel);
+ }
+ break;
+ }
+ case R_X86_64_32:
+ case R_X86_64_32S: {
+ symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+ if (symbol) {
+ addr_t value = symbol->GetAddressRef().GetFileAddress();
+ value += ELFRelocation::RelocAddend32(rel);
+ assert(
+ (reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
+ (reloc_type(rel) == R_X86_64_32S &&
+ ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
+ uint32_t truncated_addr = (value & 0xFFFFFFFF);
+ DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+ uint32_t *dst = reinterpret_cast<uint32_t *>(
+ data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
+ ELFRelocation::RelocOffset32(rel));
+ *dst = truncated_addr;
}
+ break;
+ }
+ case R_X86_64_PC32:
+ default:
+ assert(false && "unexpected relocation type");
+ }
}
+ }
- return 0;
+ return 0;
}
-unsigned
-ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, user_id_t rel_id)
-{
- assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
-
- // Parse in the section list if needed.
- SectionList *section_list = GetSectionList();
- if (!section_list)
- return 0;
-
- // Section ID's are ones based.
- user_id_t symtab_id = rel_hdr->sh_link + 1;
- user_id_t debug_id = rel_hdr->sh_info + 1;
+unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
+ user_id_t rel_id) {
+ assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
- const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
- if (!symtab_hdr)
- return 0;
-
- const ELFSectionHeader *debug_hdr = GetSectionHeaderByIndex(debug_id);
- if (!debug_hdr)
- return 0;
+ // Parse in the section list if needed.
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return 0;
- Section *rel = section_list->FindSectionByID(rel_id).get();
- if (!rel)
- return 0;
+ // Section ID's are ones based.
+ user_id_t symtab_id = rel_hdr->sh_link + 1;
+ user_id_t debug_id = rel_hdr->sh_info + 1;
- Section *symtab = section_list->FindSectionByID(symtab_id).get();
- if (!symtab)
- return 0;
+ const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
+ if (!symtab_hdr)
+ return 0;
- Section *debug = section_list->FindSectionByID(debug_id).get();
- if (!debug)
- return 0;
+ const ELFSectionHeader *debug_hdr = GetSectionHeaderByIndex(debug_id);
+ if (!debug_hdr)
+ return 0;
- DataExtractor rel_data;
- DataExtractor symtab_data;
- DataExtractor debug_data;
+ Section *rel = section_list->FindSectionByID(rel_id).get();
+ if (!rel)
+ return 0;
- if (ReadSectionData(rel, rel_data) &&
- ReadSectionData(symtab, symtab_data) &&
- ReadSectionData(debug, debug_data))
- {
- RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, debug_hdr,
- rel_data, symtab_data, debug_data, debug);
- }
+ Section *symtab = section_list->FindSectionByID(symtab_id).get();
+ if (!symtab)
+ return 0;
+ Section *debug = section_list->FindSectionByID(debug_id).get();
+ if (!debug)
return 0;
-}
-Symtab *
-ObjectFileELF::GetSymtab()
-{
- ModuleSP module_sp(GetModule());
- if (!module_sp)
- return NULL;
-
- // We always want to use the main object file so we (hopefully) only have one cached copy
- // of our symtab, dynamic sections, etc.
- ObjectFile *module_obj_file = module_sp->GetObjectFile();
- if (module_obj_file && module_obj_file != this)
- return module_obj_file->GetSymtab();
-
- if (m_symtab_ap.get() == NULL)
- {
- SectionList *section_list = module_sp->GetSectionList();
- if (!section_list)
- return NULL;
-
- uint64_t symbol_id = 0;
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
-
- // Sharable objects and dynamic executables usually have 2 distinct symbol
- // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
- // version of the symtab that only contains global symbols. The information found
- // in the dynsym is therefore also found in the symtab, while the reverse is not
- // necessarily true.
- Section *symtab = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get();
- if (!symtab)
- {
- // The symtab section is non-allocable and can be stripped, so if it doesn't exist
- // then use the dynsym section which should always be there.
- symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
- }
- if (symtab)
- {
- m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));
- symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
- }
-
- // DT_JMPREL
- // If present, this entry's d_ptr member holds the address of relocation
- // entries associated solely with the procedure linkage table. Separating
- // these relocation entries lets the dynamic linker ignore them during
- // process initialization, if lazy binding is enabled. If this entry is
- // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
- // also be present.
- const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
- if (symbol)
- {
- // Synthesize trampoline symbols to help navigate the PLT.
- addr_t addr = symbol->d_ptr;
- Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
- if (reloc_section)
- {
- user_id_t reloc_id = reloc_section->GetID();
- const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);
- assert(reloc_header);
+ DataExtractor rel_data;
+ DataExtractor symtab_data;
+ DataExtractor debug_data;
+
+ if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) &&
+ ReadSectionData(debug, debug_data)) {
+ RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr,
+ debug_hdr, rel_data, symtab_data, debug_data, debug);
+ }
+
+ return 0;
+}
+
+Symtab *ObjectFileELF::GetSymtab() {
+ ModuleSP module_sp(GetModule());
+ if (!module_sp)
+ return NULL;
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));
+ // We always want to use the main object file so we (hopefully) only have one
+ // cached copy
+ // of our symtab, dynamic sections, etc.
+ ObjectFile *module_obj_file = module_sp->GetObjectFile();
+ if (module_obj_file && module_obj_file != this)
+ return module_obj_file->GetSymtab();
- ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);
- }
- }
+ if (m_symtab_ap.get() == NULL) {
+ SectionList *section_list = module_sp->GetSectionList();
+ if (!section_list)
+ return NULL;
- DWARFCallFrameInfo* eh_frame = GetUnwindTable().GetEHFrameInfo();
- if (eh_frame)
- {
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(this));
- ParseUnwindSymbols (m_symtab_ap.get(), eh_frame);
- }
+ uint64_t symbol_id = 0;
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- // If we still don't have any symtab then create an empty instance to avoid do the section
- // lookup next time.
- if (m_symtab_ap == nullptr)
- m_symtab_ap.reset(new Symtab(this));
+ // Sharable objects and dynamic executables usually have 2 distinct symbol
+ // tables, one named ".symtab", and the other ".dynsym". The dynsym is a
+ // smaller
+ // version of the symtab that only contains global symbols. The information
+ // found
+ // in the dynsym is therefore also found in the symtab, while the reverse is
+ // not
+ // necessarily true.
+ Section *symtab =
+ section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
+ if (!symtab) {
+ // The symtab section is non-allocable and can be stripped, so if it
+ // doesn't exist
+ // then use the dynsym section which should always be there.
+ symtab =
+ section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
+ .get();
+ }
+ if (symtab) {
+ m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));
+ symbol_id += ParseSymbolTable(m_symtab_ap.get(), symbol_id, symtab);
+ }
+
+ // DT_JMPREL
+ // If present, this entry's d_ptr member holds the address of
+ // relocation
+ // entries associated solely with the procedure linkage table.
+ // Separating
+ // these relocation entries lets the dynamic linker ignore them during
+ // process initialization, if lazy binding is enabled. If this entry is
+ // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must
+ // also be present.
+ const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
+ if (symbol) {
+ // Synthesize trampoline symbols to help navigate the PLT.
+ addr_t addr = symbol->d_ptr;
+ Section *reloc_section =
+ section_list->FindSectionContainingFileAddress(addr).get();
+ if (reloc_section) {
+ user_id_t reloc_id = reloc_section->GetID();
+ const ELFSectionHeaderInfo *reloc_header =
+ GetSectionHeaderByIndex(reloc_id);
+ assert(reloc_header);
- m_symtab_ap->CalculateSymbolSizes();
- }
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));
- for (SectionHeaderCollIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I)
- {
- if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL)
- {
- if (CalculateType() == eTypeObjectFile)
- {
- const char *section_name = I->section_name.AsCString("");
- if (strstr(section_name, ".rela.debug") ||
- strstr(section_name, ".rel.debug"))
- {
- const ELFSectionHeader &reloc_header = *I;
- user_id_t reloc_id = SectionIndex(I);
- RelocateDebugSections(&reloc_header, reloc_id);
- }
- }
- }
+ ParseTrampolineSymbols(m_symtab_ap.get(), symbol_id, reloc_header,
+ reloc_id);
+ }
+ }
+
+ DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo();
+ if (eh_frame) {
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(this));
+ ParseUnwindSymbols(m_symtab_ap.get(), eh_frame);
+ }
+
+ // If we still don't have any symtab then create an empty instance to avoid
+ // do the section
+ // lookup next time.
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(this));
+
+ m_symtab_ap->CalculateSymbolSizes();
+ }
+
+ for (SectionHeaderCollIter I = m_section_headers.begin();
+ I != m_section_headers.end(); ++I) {
+ if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) {
+ if (CalculateType() == eTypeObjectFile) {
+ const char *section_name = I->section_name.AsCString("");
+ if (strstr(section_name, ".rela.debug") ||
+ strstr(section_name, ".rel.debug")) {
+ const ELFSectionHeader &reloc_header = *I;
+ user_id_t reloc_id = SectionIndex(I);
+ RelocateDebugSections(&reloc_header, reloc_id);
+ }
+ }
+ }
+ }
+ return m_symtab_ap.get();
+}
+
+void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
+ DWARFCallFrameInfo *eh_frame) {
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return;
+
+ // First we save the new symbols into a separate list and add them to the
+ // symbol table after
+ // we colleced all symbols we want to add. This is neccessary because adding a
+ // new symbol
+ // invalidates the internal index of the symtab what causing the next lookup
+ // to be slow because
+ // it have to recalculate the index first.
+ std::vector<Symbol> new_symbols;
+
+ eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
+ lldb::addr_t file_addr, uint32_t size, dw_offset_t) {
+ Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
+ if (symbol) {
+ if (!symbol->GetByteSizeIsValid()) {
+ symbol->SetByteSize(size);
+ symbol->SetSizeIsSynthesized(true);
+ }
+ } else {
+ SectionSP section_sp =
+ section_list->FindSectionContainingFileAddress(file_addr);
+ if (section_sp) {
+ addr_t offset = file_addr - section_sp->GetFileAddress();
+ const char *symbol_name = GetNextSyntheticSymbolName().GetCString();
+ uint64_t symbol_id = symbol_table->GetNumSymbols();
+ Symbol eh_symbol(
+ symbol_id, // Symbol table index.
+ symbol_name, // Symbol name.
+ false, // Is the symbol name mangled?
+ eSymbolTypeCode, // Type of this symbol.
+ true, // Is this globally visible?
+ false, // Is this symbol debug info?
+ false, // Is this symbol a trampoline?
+ true, // Is this symbol artificial?
+ section_sp, // Section in which this symbol is defined or null.
+ offset, // Offset in section or symbol value.
+ 0, // Size: Don't specify the size as an FDE can
+ false, // Size is valid: cover multiple symbols.
+ false, // Contains linker annotations?
+ 0); // Symbol flags.
+ new_symbols.push_back(eh_symbol);
+ }
}
- return m_symtab_ap.get();
-}
-
-void
-ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, DWARFCallFrameInfo* eh_frame)
-{
- SectionList* section_list = GetSectionList();
- if (!section_list)
- return;
-
- // First we save the new symbols into a separate list and add them to the symbol table after
- // we colleced all symbols we want to add. This is neccessary because adding a new symbol
- // invalidates the internal index of the symtab what causing the next lookup to be slow because
- // it have to recalculate the index first.
- std::vector<Symbol> new_symbols;
-
- eh_frame->ForEachFDEEntries(
- [this, symbol_table, section_list, &new_symbols](lldb::addr_t file_addr,
- uint32_t size,
- dw_offset_t) {
- Symbol* symbol = symbol_table->FindSymbolAtFileAddress(file_addr);
- if (symbol)
- {
- if (!symbol->GetByteSizeIsValid())
- {
- symbol->SetByteSize(size);
- symbol->SetSizeIsSynthesized(true);
- }
- }
- else
- {
- SectionSP section_sp = section_list->FindSectionContainingFileAddress(file_addr);
- if (section_sp)
- {
- addr_t offset = file_addr - section_sp->GetFileAddress();
- const char* symbol_name = GetNextSyntheticSymbolName().GetCString();
- uint64_t symbol_id = symbol_table->GetNumSymbols();
- Symbol eh_symbol(
- symbol_id, // Symbol table index.
- symbol_name, // Symbol name.
- false, // Is the symbol name mangled?
- eSymbolTypeCode, // Type of this symbol.
- true, // Is this globally visible?
- false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
- true, // Is this symbol artificial?
- section_sp, // Section in which this symbol is defined or null.
- offset, // Offset in section or symbol value.
- 0, // Size: Don't specify the size as an FDE can
- false, // Size is valid: cover multiple symbols.
- false, // Contains linker annotations?
- 0); // Symbol flags.
- new_symbols.push_back(eh_symbol);
- }
- }
- return true;
- });
+ return true;
+ });
- for (const Symbol& s : new_symbols)
- symbol_table->AddSymbol(s);
+ for (const Symbol &s : new_symbols)
+ symbol_table->AddSymbol(s);
}
-bool
-ObjectFileELF::IsStripped ()
-{
- // TODO: determine this for ELF
- return false;
+bool ObjectFileELF::IsStripped() {
+ // TODO: determine this for ELF
+ return false;
}
//===----------------------------------------------------------------------===//
@@ -3142,40 +2995,38 @@ ObjectFileELF::IsStripped ()
// Dump the specifics of the runtime file container (such as any headers
// segments, sections, etc).
//----------------------------------------------------------------------
-void
-ObjectFileELF::Dump(Stream *s)
-{
- ModuleSP module_sp(GetModule());
- if (!module_sp)
- {
- return;
- }
-
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- s->Printf("%p: ", static_cast<void *>(this));
- s->Indent();
- s->PutCString("ObjectFileELF");
-
- ArchSpec header_arch;
- GetArchitecture(header_arch);
-
- *s << ", file = '" << m_file << "', arch = " << header_arch.GetArchitectureName() << "\n";
-
- DumpELFHeader(s, m_header);
- s->EOL();
- DumpELFProgramHeaders(s);
- s->EOL();
- DumpELFSectionHeaders(s);
- s->EOL();
- SectionList *section_list = GetSectionList();
- if (section_list)
- section_list->Dump(s, NULL, true, UINT32_MAX);
- Symtab *symtab = GetSymtab();
- if (symtab)
- symtab->Dump(s, NULL, eSortOrderNone);
- s->EOL();
- DumpDependentModules(s);
- s->EOL();
+void ObjectFileELF::Dump(Stream *s) {
+ ModuleSP module_sp(GetModule());
+ if (!module_sp) {
+ return;
+ }
+
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ s->Printf("%p: ", static_cast<void *>(this));
+ s->Indent();
+ s->PutCString("ObjectFileELF");
+
+ ArchSpec header_arch;
+ GetArchitecture(header_arch);
+
+ *s << ", file = '" << m_file
+ << "', arch = " << header_arch.GetArchitectureName() << "\n";
+
+ DumpELFHeader(s, m_header);
+ s->EOL();
+ DumpELFProgramHeaders(s);
+ s->EOL();
+ DumpELFSectionHeaders(s);
+ s->EOL();
+ SectionList *section_list = GetSectionList();
+ if (section_list)
+ section_list->Dump(s, NULL, true, UINT32_MAX);
+ Symtab *symtab = GetSymtab();
+ if (symtab)
+ symtab->Dump(s, NULL, eSortOrderNone);
+ s->EOL();
+ DumpDependentModules(s);
+ s->EOL();
}
//----------------------------------------------------------------------
@@ -3183,38 +3034,36 @@ ObjectFileELF::Dump(Stream *s)
//
// Dump the ELF header to the specified output stream
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header)
-{
- s->PutCString("ELF Header\n");
- s->Printf("e_ident[EI_MAG0 ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
- s->Printf("e_ident[EI_MAG1 ] = 0x%2.2x '%c'\n",
- header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]);
- s->Printf("e_ident[EI_MAG2 ] = 0x%2.2x '%c'\n",
- header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]);
- s->Printf("e_ident[EI_MAG3 ] = 0x%2.2x '%c'\n",
- header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]);
-
- s->Printf("e_ident[EI_CLASS ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
- s->Printf("e_ident[EI_DATA ] = 0x%2.2x ", header.e_ident[EI_DATA]);
- DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
- s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
- s->Printf ("e_ident[EI_PAD ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
-
- s->Printf("e_type = 0x%4.4x ", header.e_type);
- DumpELFHeader_e_type(s, header.e_type);
- s->Printf("\ne_machine = 0x%4.4x\n", header.e_machine);
- s->Printf("e_version = 0x%8.8x\n", header.e_version);
- s->Printf("e_entry = 0x%8.8" PRIx64 "\n", header.e_entry);
- s->Printf("e_phoff = 0x%8.8" PRIx64 "\n", header.e_phoff);
- s->Printf("e_shoff = 0x%8.8" PRIx64 "\n", header.e_shoff);
- s->Printf("e_flags = 0x%8.8x\n", header.e_flags);
- s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize);
- s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
- s->Printf("e_phnum = 0x%4.4x\n", header.e_phnum);
- s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
- s->Printf("e_shnum = 0x%4.4x\n", header.e_shnum);
- s->Printf("e_shstrndx = 0x%4.4x\n", header.e_shstrndx);
+void ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header) {
+ s->PutCString("ELF Header\n");
+ s->Printf("e_ident[EI_MAG0 ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
+ s->Printf("e_ident[EI_MAG1 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG1],
+ header.e_ident[EI_MAG1]);
+ s->Printf("e_ident[EI_MAG2 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG2],
+ header.e_ident[EI_MAG2]);
+ s->Printf("e_ident[EI_MAG3 ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG3],
+ header.e_ident[EI_MAG3]);
+
+ s->Printf("e_ident[EI_CLASS ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
+ s->Printf("e_ident[EI_DATA ] = 0x%2.2x ", header.e_ident[EI_DATA]);
+ DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
+ s->Printf("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
+ s->Printf("e_ident[EI_PAD ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
+
+ s->Printf("e_type = 0x%4.4x ", header.e_type);
+ DumpELFHeader_e_type(s, header.e_type);
+ s->Printf("\ne_machine = 0x%4.4x\n", header.e_machine);
+ s->Printf("e_version = 0x%8.8x\n", header.e_version);
+ s->Printf("e_entry = 0x%8.8" PRIx64 "\n", header.e_entry);
+ s->Printf("e_phoff = 0x%8.8" PRIx64 "\n", header.e_phoff);
+ s->Printf("e_shoff = 0x%8.8" PRIx64 "\n", header.e_shoff);
+ s->Printf("e_flags = 0x%8.8x\n", header.e_flags);
+ s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize);
+ s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
+ s->Printf("e_phnum = 0x%4.4x\n", header.e_phnum);
+ s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
+ s->Printf("e_shnum = 0x%4.4x\n", header.e_shnum);
+ s->Printf("e_shstrndx = 0x%4.4x\n", header.e_shstrndx);
}
//----------------------------------------------------------------------
@@ -3222,19 +3071,26 @@ ObjectFileELF::DumpELFHeader(Stream *s,
//
// Dump an token value for the ELF header member e_type
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type)
-{
- switch (e_type)
- {
- case ET_NONE: *s << "ET_NONE"; break;
- case ET_REL: *s << "ET_REL"; break;
- case ET_EXEC: *s << "ET_EXEC"; break;
- case ET_DYN: *s << "ET_DYN"; break;
- case ET_CORE: *s << "ET_CORE"; break;
- default:
- break;
- }
+void ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type) {
+ switch (e_type) {
+ case ET_NONE:
+ *s << "ET_NONE";
+ break;
+ case ET_REL:
+ *s << "ET_REL";
+ break;
+ case ET_EXEC:
+ *s << "ET_EXEC";
+ break;
+ case ET_DYN:
+ *s << "ET_DYN";
+ break;
+ case ET_CORE:
+ *s << "ET_CORE";
+ break;
+ default:
+ break;
+ }
}
//----------------------------------------------------------------------
@@ -3242,34 +3098,38 @@ ObjectFileELF::DumpELFHeader_e_type(Stre
//
// Dump an token value for the ELF header member e_ident[EI_DATA]
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, unsigned char ei_data)
-{
- switch (ei_data)
- {
- case ELFDATANONE: *s << "ELFDATANONE"; break;
- case ELFDATA2LSB: *s << "ELFDATA2LSB - Little Endian"; break;
- case ELFDATA2MSB: *s << "ELFDATA2MSB - Big Endian"; break;
- default:
- break;
- }
+void ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s,
+ unsigned char ei_data) {
+ switch (ei_data) {
+ case ELFDATANONE:
+ *s << "ELFDATANONE";
+ break;
+ case ELFDATA2LSB:
+ *s << "ELFDATA2LSB - Little Endian";
+ break;
+ case ELFDATA2MSB:
+ *s << "ELFDATA2MSB - Big Endian";
+ break;
+ default:
+ break;
+ }
}
-
//----------------------------------------------------------------------
// DumpELFProgramHeader
//
// Dump a single ELF program header to the specified output stream
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFProgramHeader(Stream *s, const ELFProgramHeader &ph)
-{
- DumpELFProgramHeader_p_type(s, ph.p_type);
- s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset, ph.p_vaddr, ph.p_paddr);
- s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
+void ObjectFileELF::DumpELFProgramHeader(Stream *s,
+ const ELFProgramHeader &ph) {
+ DumpELFProgramHeader_p_type(s, ph.p_type);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset,
+ ph.p_vaddr, ph.p_paddr);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz,
+ ph.p_flags);
- DumpELFProgramHeader_p_flags(s, ph.p_flags);
- s->Printf(") %8.8" PRIx64, ph.p_align);
+ DumpELFProgramHeader_p_flags(s, ph.p_flags);
+ s->Printf(") %8.8" PRIx64, ph.p_align);
}
//----------------------------------------------------------------------
@@ -3278,41 +3138,35 @@ ObjectFileELF::DumpELFProgramHeader(Stre
// Dump an token value for the ELF program header member p_type which
// describes the type of the program header
// ----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
-{
- const int kStrWidth = 15;
- switch (p_type)
- {
- CASE_AND_STREAM(s, PT_NULL , kStrWidth);
- CASE_AND_STREAM(s, PT_LOAD , kStrWidth);
- CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth);
- CASE_AND_STREAM(s, PT_INTERP , kStrWidth);
- CASE_AND_STREAM(s, PT_NOTE , kStrWidth);
- CASE_AND_STREAM(s, PT_SHLIB , kStrWidth);
- CASE_AND_STREAM(s, PT_PHDR , kStrWidth);
- CASE_AND_STREAM(s, PT_TLS , kStrWidth);
+void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
+ const int kStrWidth = 15;
+ switch (p_type) {
+ CASE_AND_STREAM(s, PT_NULL, kStrWidth);
+ CASE_AND_STREAM(s, PT_LOAD, kStrWidth);
+ CASE_AND_STREAM(s, PT_DYNAMIC, kStrWidth);
+ CASE_AND_STREAM(s, PT_INTERP, kStrWidth);
+ CASE_AND_STREAM(s, PT_NOTE, kStrWidth);
+ CASE_AND_STREAM(s, PT_SHLIB, kStrWidth);
+ CASE_AND_STREAM(s, PT_PHDR, kStrWidth);
+ CASE_AND_STREAM(s, PT_TLS, kStrWidth);
CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
- default:
- s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
- break;
- }
+ default:
+ s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
+ break;
+ }
}
-
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_flags
//
// Dump an token value for the ELF program header member p_flags
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags)
-{
- *s << ((p_flags & PF_X) ? "PF_X" : " ")
- << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
- << ((p_flags & PF_W) ? "PF_W" : " ")
- << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
- << ((p_flags & PF_R) ? "PF_R" : " ");
+void ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags) {
+ *s << ((p_flags & PF_X) ? "PF_X" : " ")
+ << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
+ << ((p_flags & PF_W) ? "PF_W" : " ")
+ << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
+ << ((p_flags & PF_R) ? "PF_R" : " ");
}
//----------------------------------------------------------------------
@@ -3320,26 +3174,23 @@ ObjectFileELF::DumpELFProgramHeader_p_fl
//
// Dump all of the ELF program header to the specified output stream
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFProgramHeaders(Stream *s)
-{
- if (!ParseProgramHeaders())
- return;
-
- s->PutCString("Program Headers\n");
- s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
- "p_filesz p_memsz p_flags p_align\n");
- s->PutCString("==== --------------- -------- -------- -------- "
- "-------- -------- ------------------------- --------\n");
-
- uint32_t idx = 0;
- for (ProgramHeaderCollConstIter I = m_program_headers.begin();
- I != m_program_headers.end(); ++I, ++idx)
- {
- s->Printf("[%2u] ", idx);
- ObjectFileELF::DumpELFProgramHeader(s, *I);
- s->EOL();
- }
+void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
+ if (!ParseProgramHeaders())
+ return;
+
+ s->PutCString("Program Headers\n");
+ s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
+ "p_filesz p_memsz p_flags p_align\n");
+ s->PutCString("==== --------------- -------- -------- -------- "
+ "-------- -------- ------------------------- --------\n");
+
+ uint32_t idx = 0;
+ for (ProgramHeaderCollConstIter I = m_program_headers.begin();
+ I != m_program_headers.end(); ++I, ++idx) {
+ s->Printf("[%2u] ", idx);
+ ObjectFileELF::DumpELFProgramHeader(s, *I);
+ s->EOL();
+ }
}
//----------------------------------------------------------------------
@@ -3347,16 +3198,16 @@ ObjectFileELF::DumpELFProgramHeaders(Str
//
// Dump a single ELF section header to the specified output stream
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeaderInfo &sh)
-{
- s->Printf("%8.8x ", sh.sh_name);
- DumpELFSectionHeader_sh_type(s, sh.sh_type);
- s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
- DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
- s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr, sh.sh_offset, sh.sh_size);
- s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
- s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
+void ObjectFileELF::DumpELFSectionHeader(Stream *s,
+ const ELFSectionHeaderInfo &sh) {
+ s->Printf("%8.8x ", sh.sh_name);
+ DumpELFSectionHeader_sh_type(s, sh.sh_type);
+ s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
+ DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
+ s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr,
+ sh.sh_offset, sh.sh_size);
+ s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
+ s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
}
//----------------------------------------------------------------------
@@ -3365,32 +3216,29 @@ ObjectFileELF::DumpELFSectionHeader(Stre
// Dump an token value for the ELF section header member sh_type which
// describes the type of the section
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type)
-{
- const int kStrWidth = 12;
- switch (sh_type)
- {
- CASE_AND_STREAM(s, SHT_NULL , kStrWidth);
- CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth);
- CASE_AND_STREAM(s, SHT_SYMTAB , kStrWidth);
- CASE_AND_STREAM(s, SHT_STRTAB , kStrWidth);
- CASE_AND_STREAM(s, SHT_RELA , kStrWidth);
- CASE_AND_STREAM(s, SHT_HASH , kStrWidth);
- CASE_AND_STREAM(s, SHT_DYNAMIC , kStrWidth);
- CASE_AND_STREAM(s, SHT_NOTE , kStrWidth);
- CASE_AND_STREAM(s, SHT_NOBITS , kStrWidth);
- CASE_AND_STREAM(s, SHT_REL , kStrWidth);
- CASE_AND_STREAM(s, SHT_SHLIB , kStrWidth);
- CASE_AND_STREAM(s, SHT_DYNSYM , kStrWidth);
- CASE_AND_STREAM(s, SHT_LOPROC , kStrWidth);
- CASE_AND_STREAM(s, SHT_HIPROC , kStrWidth);
- CASE_AND_STREAM(s, SHT_LOUSER , kStrWidth);
- CASE_AND_STREAM(s, SHT_HIUSER , kStrWidth);
- default:
- s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
- break;
- }
+void ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type) {
+ const int kStrWidth = 12;
+ switch (sh_type) {
+ CASE_AND_STREAM(s, SHT_NULL, kStrWidth);
+ CASE_AND_STREAM(s, SHT_PROGBITS, kStrWidth);
+ CASE_AND_STREAM(s, SHT_SYMTAB, kStrWidth);
+ CASE_AND_STREAM(s, SHT_STRTAB, kStrWidth);
+ CASE_AND_STREAM(s, SHT_RELA, kStrWidth);
+ CASE_AND_STREAM(s, SHT_HASH, kStrWidth);
+ CASE_AND_STREAM(s, SHT_DYNAMIC, kStrWidth);
+ CASE_AND_STREAM(s, SHT_NOTE, kStrWidth);
+ CASE_AND_STREAM(s, SHT_NOBITS, kStrWidth);
+ CASE_AND_STREAM(s, SHT_REL, kStrWidth);
+ CASE_AND_STREAM(s, SHT_SHLIB, kStrWidth);
+ CASE_AND_STREAM(s, SHT_DYNSYM, kStrWidth);
+ CASE_AND_STREAM(s, SHT_LOPROC, kStrWidth);
+ CASE_AND_STREAM(s, SHT_HIPROC, kStrWidth);
+ CASE_AND_STREAM(s, SHT_LOUSER, kStrWidth);
+ CASE_AND_STREAM(s, SHT_HIUSER, kStrWidth);
+ default:
+ s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
+ break;
+ }
}
//----------------------------------------------------------------------
@@ -3398,14 +3246,13 @@ ObjectFileELF::DumpELFSectionHeader_sh_t
//
// Dump an token value for the ELF section header member sh_flags
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags)
-{
- *s << ((sh_flags & SHF_WRITE) ? "WRITE" : " ")
- << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
- << ((sh_flags & SHF_ALLOC) ? "ALLOC" : " ")
- << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
- << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : " ");
+void ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s,
+ elf_xword sh_flags) {
+ *s << ((sh_flags & SHF_WRITE) ? "WRITE" : " ")
+ << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
+ << ((sh_flags & SHF_ALLOC) ? "ALLOC" : " ")
+ << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
+ << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : " ");
}
//----------------------------------------------------------------------
@@ -3413,153 +3260,135 @@ ObjectFileELF::DumpELFSectionHeader_sh_f
//
// Dump all of the ELF section header to the specified output stream
//----------------------------------------------------------------------
-void
-ObjectFileELF::DumpELFSectionHeaders(Stream *s)
-{
- if (!ParseSectionHeaders())
- return;
-
- s->PutCString("Section Headers\n");
- s->PutCString("IDX name type flags "
- "addr offset size link info addralgn "
- "entsize Name\n");
- s->PutCString("==== -------- ------------ -------------------------------- "
- "-------- -------- -------- -------- -------- -------- "
- "-------- ====================\n");
-
- uint32_t idx = 0;
- for (SectionHeaderCollConstIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I, ++idx)
- {
- s->Printf("[%2u] ", idx);
- ObjectFileELF::DumpELFSectionHeader(s, *I);
- const char* section_name = I->section_name.AsCString("");
- if (section_name)
- *s << ' ' << section_name << "\n";
- }
-}
-
-void
-ObjectFileELF::DumpDependentModules(lldb_private::Stream *s)
-{
- size_t num_modules = ParseDependentModules();
-
- if (num_modules > 0)
- {
- s->PutCString("Dependent Modules:\n");
- for (unsigned i = 0; i < num_modules; ++i)
- {
- const FileSpec &spec = m_filespec_ap->GetFileSpecAtIndex(i);
- s->Printf(" %s\n", spec.GetFilename().GetCString());
- }
- }
-}
-
-bool
-ObjectFileELF::GetArchitecture (ArchSpec &arch)
-{
- if (!ParseHeader())
- return false;
-
- if (m_section_headers.empty())
- {
- // Allow elf notes to be parsed which may affect the detected architecture.
- ParseSectionHeaders();
- }
-
- if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown())
- {
- // Core files don't have section headers yet they have PT_NOTE program headers
- // that might shed more light on the architecture
- if (ParseProgramHeaders())
- {
- for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
- {
- const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
- if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0)
- {
- DataExtractor data;
- if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz)
- {
- lldb_private::UUID uuid;
- RefineModuleDetailsFromNote (data, m_arch_spec, uuid);
- }
- }
- }
- }
+void ObjectFileELF::DumpELFSectionHeaders(Stream *s) {
+ if (!ParseSectionHeaders())
+ return;
+
+ s->PutCString("Section Headers\n");
+ s->PutCString("IDX name type flags "
+ "addr offset size link info addralgn "
+ "entsize Name\n");
+ s->PutCString("==== -------- ------------ -------------------------------- "
+ "-------- -------- -------- -------- -------- -------- "
+ "-------- ====================\n");
+
+ uint32_t idx = 0;
+ for (SectionHeaderCollConstIter I = m_section_headers.begin();
+ I != m_section_headers.end(); ++I, ++idx) {
+ s->Printf("[%2u] ", idx);
+ ObjectFileELF::DumpELFSectionHeader(s, *I);
+ const char *section_name = I->section_name.AsCString("");
+ if (section_name)
+ *s << ' ' << section_name << "\n";
+ }
+}
+
+void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
+ size_t num_modules = ParseDependentModules();
+
+ if (num_modules > 0) {
+ s->PutCString("Dependent Modules:\n");
+ for (unsigned i = 0; i < num_modules; ++i) {
+ const FileSpec &spec = m_filespec_ap->GetFileSpecAtIndex(i);
+ s->Printf(" %s\n", spec.GetFilename().GetCString());
}
- arch = m_arch_spec;
- return true;
+ }
}
-ObjectFile::Type
-ObjectFileELF::CalculateType()
-{
- switch (m_header.e_type)
- {
- case llvm::ELF::ET_NONE:
- // 0 - No file type
- return eTypeUnknown;
-
- case llvm::ELF::ET_REL:
- // 1 - Relocatable file
- return eTypeObjectFile;
-
- case llvm::ELF::ET_EXEC:
- // 2 - Executable file
- return eTypeExecutable;
-
- case llvm::ELF::ET_DYN:
- // 3 - Shared object file
- return eTypeSharedLibrary;
-
- case ET_CORE:
- // 4 - Core file
- return eTypeCoreFile;
+bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
+ if (!ParseHeader())
+ return false;
- default:
- break;
- }
+ if (m_section_headers.empty()) {
+ // Allow elf notes to be parsed which may affect the detected architecture.
+ ParseSectionHeaders();
+ }
+
+ if (CalculateType() == eTypeCoreFile &&
+ m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
+ // Core files don't have section headers yet they have PT_NOTE program
+ // headers
+ // that might shed more light on the architecture
+ if (ParseProgramHeaders()) {
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) {
+ const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
+ if (header && header->p_type == PT_NOTE && header->p_offset != 0 &&
+ header->p_filesz > 0) {
+ DataExtractor data;
+ if (data.SetData(m_data, header->p_offset, header->p_filesz) ==
+ header->p_filesz) {
+ lldb_private::UUID uuid;
+ RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
+ }
+ }
+ }
+ }
+ }
+ arch = m_arch_spec;
+ return true;
+}
+
+ObjectFile::Type ObjectFileELF::CalculateType() {
+ switch (m_header.e_type) {
+ case llvm::ELF::ET_NONE:
+ // 0 - No file type
return eTypeUnknown;
-}
-ObjectFile::Strata
-ObjectFileELF::CalculateStrata()
-{
- switch (m_header.e_type)
- {
- case llvm::ELF::ET_NONE:
- // 0 - No file type
- return eStrataUnknown;
-
- case llvm::ELF::ET_REL:
- // 1 - Relocatable file
- return eStrataUnknown;
-
- case llvm::ELF::ET_EXEC:
- // 2 - Executable file
- // TODO: is there any way to detect that an executable is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
- return eStrataUser;
-
- case llvm::ELF::ET_DYN:
- // 3 - Shared object file
- // TODO: is there any way to detect that an shared library is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
- return eStrataUnknown;
-
- case ET_CORE:
- // 4 - Core file
- // TODO: is there any way to detect that an core file is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
- return eStrataUnknown;
+ case llvm::ELF::ET_REL:
+ // 1 - Relocatable file
+ return eTypeObjectFile;
+
+ case llvm::ELF::ET_EXEC:
+ // 2 - Executable file
+ return eTypeExecutable;
+
+ case llvm::ELF::ET_DYN:
+ // 3 - Shared object file
+ return eTypeSharedLibrary;
+
+ case ET_CORE:
+ // 4 - Core file
+ return eTypeCoreFile;
+
+ default:
+ break;
+ }
+ return eTypeUnknown;
+}
+
+ObjectFile::Strata ObjectFileELF::CalculateStrata() {
+ switch (m_header.e_type) {
+ case llvm::ELF::ET_NONE:
+ // 0 - No file type
+ return eStrataUnknown;
- default:
- break;
- }
+ case llvm::ELF::ET_REL:
+ // 1 - Relocatable file
+ return eStrataUnknown;
+
+ case llvm::ELF::ET_EXEC:
+ // 2 - Executable file
+ // TODO: is there any way to detect that an executable is a kernel
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
+ return eStrataUser;
+
+ case llvm::ELF::ET_DYN:
+ // 3 - Shared object file
+ // TODO: is there any way to detect that an shared library is a kernel
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
return eStrataUnknown;
-}
+ case ET_CORE:
+ // 4 - Core file
+ // TODO: is there any way to detect that an core file is a kernel
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
+ return eStrataUnknown;
+
+ default:
+ break;
+ }
+ return eStrataUnknown;
+}
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Tue Sep 6 15:57:50 2016
@@ -19,46 +19,40 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/UUID.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Core/UUID.h"
-#include "lldb/Core/ArchSpec.h"
+#include "lldb/lldb-private.h"
#include "ELFHeader.h"
-struct ELFNote
-{
- elf::elf_word n_namesz;
- elf::elf_word n_descsz;
- elf::elf_word n_type;
-
- std::string n_name;
-
- ELFNote() : n_namesz(0), n_descsz(0), n_type(0)
- {
- }
-
- /// Parse an ELFNote entry from the given DataExtractor starting at position
- /// \p offset.
- ///
- /// @param[in] data
- /// The DataExtractor to read from.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFRel entry was successfully read and false otherwise.
- bool
- Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
-
- size_t
- GetByteSize() const
- {
- return 12 + llvm::alignTo (n_namesz, 4) + llvm::alignTo (n_descsz, 4);
- }
+struct ELFNote {
+ elf::elf_word n_namesz;
+ elf::elf_word n_descsz;
+ elf::elf_word n_type;
+
+ std::string n_name;
+
+ ELFNote() : n_namesz(0), n_descsz(0), n_type(0) {}
+
+ /// Parse an ELFNote entry from the given DataExtractor starting at position
+ /// \p offset.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFRel entry was successfully read and false otherwise.
+ bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ size_t GetByteSize() const {
+ return 12 + llvm::alignTo(n_namesz, 4) + llvm::alignTo(n_descsz, 4);
+ }
};
//------------------------------------------------------------------------------
@@ -67,390 +61,332 @@ struct ELFNote
///
/// This class provides a generic ELF (32/64 bit) reader plugin implementing the
/// ObjectFile protocol.
-class ObjectFileELF :
- public lldb_private::ObjectFile
-{
+class ObjectFileELF : public lldb_private::ObjectFile {
public:
- ~ObjectFileELF() override;
+ ~ObjectFileELF() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::ObjectFile *
- CreateInstance(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec* file,
- lldb::offset_t file_offset,
- lldb::offset_t length);
-
- static lldb_private::ObjectFile *
- CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- const lldb::ProcessSP &process_sp,
- lldb::addr_t header_addr);
-
- static size_t
- GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs);
-
- static bool
- MagicBytesMatch (lldb::DataBufferSP& data_sp,
- lldb::addr_t offset,
- lldb::addr_t length);
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- //------------------------------------------------------------------
- // ObjectFile Protocol.
- //------------------------------------------------------------------
- bool
- ParseHeader() override;
-
- bool
- SetLoadAddress (lldb_private::Target &target,
- lldb::addr_t value,
- bool value_is_offset) override;
-
- lldb::ByteOrder
- GetByteOrder() const override;
-
- bool
- IsExecutable () const override;
-
- uint32_t
- GetAddressByteSize() const override;
-
- lldb::AddressClass
- GetAddressClass (lldb::addr_t file_addr) override;
-
- lldb_private::Symtab *
- GetSymtab() override;
-
- bool
- IsStripped () override;
-
- void
- CreateSections (lldb_private::SectionList &unified_section_list) override;
-
- void
- Dump(lldb_private::Stream *s) override;
-
- bool
- GetArchitecture (lldb_private::ArchSpec &arch) override;
-
- bool
- GetUUID(lldb_private::UUID* uuid) override;
-
- lldb_private::FileSpecList
- GetDebugSymbolFilePaths() override;
-
- uint32_t
- GetDependentModules(lldb_private::FileSpecList& files) override;
-
- lldb_private::Address
- GetImageInfoAddress(lldb_private::Target *target) override;
-
- lldb_private::Address
- GetEntryPointAddress () override;
-
- ObjectFile::Type
- CalculateType() override;
-
- ObjectFile::Strata
- CalculateStrata() override;
-
- // Returns number of program headers found in the ELF file.
- size_t
- GetProgramHeaderCount();
-
- // Returns the program header with the given index.
- const elf::ELFProgramHeader *
- GetProgramHeaderByIndex(lldb::user_id_t id);
-
- // Returns segment data for the given index.
- lldb_private::DataExtractor
- GetSegmentDataByIndex(lldb::user_id_t id);
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- std::string
- StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
+ static void Terminate();
-private:
- ObjectFileELF(const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec* file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- ObjectFileELF (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& header_data_sp,
- const lldb::ProcessSP &process_sp,
- lldb::addr_t header_addr);
-
- typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
- typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
- typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
-
- struct ELFSectionHeaderInfo : public elf::ELFSectionHeader
- {
- lldb_private::ConstString section_name;
- };
-
- typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
- typedef SectionHeaderColl::iterator SectionHeaderCollIter;
- typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
-
- typedef std::vector<elf::ELFDynamic> DynamicSymbolColl;
- typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
- typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
-
- typedef std::map<lldb::addr_t, lldb::AddressClass> FileAddressToAddressClassMap;
- typedef std::function<lldb::offset_t (lldb_private::DataExtractor &, lldb::offset_t, lldb::offset_t)> SetDataFunction;
-
- /// Version of this reader common to all plugins based on this class.
- static const uint32_t m_plugin_version = 1;
- static const uint32_t g_core_uuid_magic;
-
- /// ELF file header.
- elf::ELFHeader m_header;
-
- /// ELF build ID.
- lldb_private::UUID m_uuid;
-
- /// ELF .gnu_debuglink file and crc data if available.
- std::string m_gnu_debuglink_file;
- uint32_t m_gnu_debuglink_crc;
-
- /// Collection of program headers.
- ProgramHeaderColl m_program_headers;
-
- /// Collection of section headers.
- SectionHeaderColl m_section_headers;
-
- /// Collection of symbols from the dynamic table.
- DynamicSymbolColl m_dynamic_symbols;
-
- /// List of file specifications corresponding to the modules (shared
- /// libraries) on which this object file depends.
- mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
-
- /// Cached value of the entry point for this module.
- lldb_private::Address m_entry_point_address;
-
- /// The architecture detected from parsing elf file contents.
- lldb_private::ArchSpec m_arch_spec;
-
- /// The address class for each symbol in the elf file
- FileAddressToAddressClassMap m_address_class_map;
-
- /// Returns a 1 based index of the given section header.
- size_t
- SectionIndex(const SectionHeaderCollIter &I);
-
- /// Returns a 1 based index of the given section header.
- size_t
- SectionIndex(const SectionHeaderCollConstIter &I) const;
-
- // Parses the ELF program headers.
- static size_t
- GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
- const SetDataFunction &set_data,
- const elf::ELFHeader &header);
-
- // Finds PT_NOTE segments and calculates their crc sum.
- static uint32_t
- CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl& program_headers,
- lldb_private::DataExtractor &data);
-
- /// Parses all section headers present in this object file and populates
- /// m_program_headers. This method will compute the header list only once.
- /// Returns the number of headers parsed.
- size_t
- ParseProgramHeaders();
-
- /// Parses all section headers present in this object file and populates
- /// m_section_headers. This method will compute the header list only once.
- /// Returns the number of headers parsed.
- size_t
- ParseSectionHeaders();
-
- static void
- ParseARMAttributes(lldb_private::DataExtractor &data, uint64_t length,
- lldb_private::ArchSpec &arch_spec);
-
- /// Parses the elf section headers and returns the uuid, debug link name, crc, archspec.
- static size_t
- GetSectionHeaderInfo(SectionHeaderColl §ion_headers,
- const SetDataFunction &set_data,
- const elf::ELFHeader &header,
- lldb_private::UUID &uuid,
- std::string &gnu_debuglink_file,
- uint32_t &gnu_debuglink_crc,
- lldb_private::ArchSpec &arch_spec);
-
- /// Scans the dynamic section and locates all dependent modules (shared
- /// libraries) populating m_filespec_ap. This method will compute the
- /// dependent module list only once. Returns the number of dependent
- /// modules parsed.
- size_t
- ParseDependentModules();
-
- /// Parses the dynamic symbol table and populates m_dynamic_symbols. The
- /// vector retains the order as found in the object file. Returns the
- /// number of dynamic symbols parsed.
- size_t
- ParseDynamicSymbols();
-
- /// Populates m_symtab_ap will all non-dynamic linker symbols. This method
- /// will parse the symbols only once. Returns the number of symbols parsed.
- unsigned
- ParseSymbolTable(lldb_private::Symtab *symbol_table,
- lldb::user_id_t start_id,
- lldb_private::Section *symtab);
-
- /// Helper routine for ParseSymbolTable().
- unsigned
- ParseSymbols(lldb_private::Symtab *symbol_table,
- lldb::user_id_t start_id,
- lldb_private::SectionList *section_list,
- const size_t num_symbols,
- const lldb_private::DataExtractor &symtab_data,
- const lldb_private::DataExtractor &strtab_data);
-
- /// Scans the relocation entries and adds a set of artificial symbols to the
- /// given symbol table for each PLT slot. Returns the number of symbols
- /// added.
- unsigned
- ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,
- lldb::user_id_t start_id,
- const ELFSectionHeaderInfo *rela_hdr,
- lldb::user_id_t section_id);
-
- void
- ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
- lldb_private::DWARFCallFrameInfo* eh_frame);
-
- /// Relocates debug sections
- unsigned
- RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, lldb::user_id_t rel_id);
-
- unsigned
- RelocateSection(lldb_private::Symtab* symtab, const elf::ELFHeader *hdr, const elf::ELFSectionHeader *rel_hdr,
- const elf::ELFSectionHeader *symtab_hdr, const elf::ELFSectionHeader *debug_hdr,
- lldb_private::DataExtractor &rel_data, lldb_private::DataExtractor &symtab_data,
- lldb_private::DataExtractor &debug_data, lldb_private::Section* rel_section);
-
- /// Loads the section name string table into m_shstr_data. Returns the
- /// number of bytes constituting the table.
- size_t
- GetSectionHeaderStringTable();
-
- /// Utility method for looking up a section given its name. Returns the
- /// index of the corresponding section or zero if no section with the given
- /// name can be found (note that section indices are always 1 based, and so
- /// section index 0 is never valid).
- lldb::user_id_t
- GetSectionIndexByName(const char *name);
-
- // Returns the ID of the first section that has the given type.
- lldb::user_id_t
- GetSectionIndexByType(unsigned type);
-
- /// Returns the section header with the given id or NULL.
- const ELFSectionHeaderInfo *
- GetSectionHeaderByIndex(lldb::user_id_t id);
-
- /// @name ELF header dump routines
- //@{
- static void
- DumpELFHeader(lldb_private::Stream *s, const elf::ELFHeader& header);
-
- static void
- DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,
- unsigned char ei_data);
-
- static void
- DumpELFHeader_e_type(lldb_private::Stream *s, elf::elf_half e_type);
- //@}
-
- /// @name ELF program header dump routines
- //@{
- void
- DumpELFProgramHeaders(lldb_private::Stream *s);
-
- static void
- DumpELFProgramHeader(lldb_private::Stream *s,
- const elf::ELFProgramHeader &ph);
-
- static void
- DumpELFProgramHeader_p_type(lldb_private::Stream *s, elf::elf_word p_type);
-
- static void
- DumpELFProgramHeader_p_flags(lldb_private::Stream *s,
- elf::elf_word p_flags);
- //@}
-
- /// @name ELF section header dump routines
- //@{
- void
- DumpELFSectionHeaders(lldb_private::Stream *s);
-
- static void
- DumpELFSectionHeader(lldb_private::Stream *s,
- const ELFSectionHeaderInfo& sh);
-
- static void
- DumpELFSectionHeader_sh_type(lldb_private::Stream *s,
- elf::elf_word sh_type);
-
- static void
- DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,
- elf::elf_xword sh_flags);
- //@}
-
- /// ELF dependent module dump routine.
- void
- DumpDependentModules(lldb_private::Stream *s);
-
- const elf::ELFDynamic *
- FindDynamicSymbol(unsigned tag);
-
- unsigned
- PLTRelocationType();
-
- static lldb_private::Error
- RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectFile *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length);
+
+ static lldb_private::ObjectFile *CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+ static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
+ lldb::addr_t length);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // ObjectFile Protocol.
+ //------------------------------------------------------------------
+ bool ParseHeader() override;
+
+ bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
+ bool value_is_offset) override;
+
+ lldb::ByteOrder GetByteOrder() const override;
+
+ bool IsExecutable() const override;
+ uint32_t GetAddressByteSize() const override;
- static lldb::offset_t
- SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length);
+ lldb::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
- lldb::offset_t
- SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length);
+ lldb_private::Symtab *GetSymtab() override;
+
+ bool IsStripped() override;
+
+ void CreateSections(lldb_private::SectionList &unified_section_list) override;
+
+ void Dump(lldb_private::Stream *s) override;
+
+ bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+
+ bool GetUUID(lldb_private::UUID *uuid) override;
+
+ lldb_private::FileSpecList GetDebugSymbolFilePaths() override;
+
+ uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
+
+ lldb_private::Address
+ GetImageInfoAddress(lldb_private::Target *target) override;
+
+ lldb_private::Address GetEntryPointAddress() override;
+
+ ObjectFile::Type CalculateType() override;
+
+ ObjectFile::Strata CalculateStrata() override;
+
+ // Returns number of program headers found in the ELF file.
+ size_t GetProgramHeaderCount();
+
+ // Returns the program header with the given index.
+ const elf::ELFProgramHeader *GetProgramHeaderByIndex(lldb::user_id_t id);
+
+ // Returns segment data for the given index.
+ lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id);
+
+ std::string
+ StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
+
+private:
+ ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ ObjectFileELF(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &header_data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+ typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
+ typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
+ typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
+
+ struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
+ lldb_private::ConstString section_name;
+ };
+
+ typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
+ typedef SectionHeaderColl::iterator SectionHeaderCollIter;
+ typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
+
+ typedef std::vector<elf::ELFDynamic> DynamicSymbolColl;
+ typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
+ typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
+
+ typedef std::map<lldb::addr_t, lldb::AddressClass>
+ FileAddressToAddressClassMap;
+ typedef std::function<lldb::offset_t(lldb_private::DataExtractor &,
+ lldb::offset_t, lldb::offset_t)>
+ SetDataFunction;
+
+ /// Version of this reader common to all plugins based on this class.
+ static const uint32_t m_plugin_version = 1;
+ static const uint32_t g_core_uuid_magic;
+
+ /// ELF file header.
+ elf::ELFHeader m_header;
+
+ /// ELF build ID.
+ lldb_private::UUID m_uuid;
+
+ /// ELF .gnu_debuglink file and crc data if available.
+ std::string m_gnu_debuglink_file;
+ uint32_t m_gnu_debuglink_crc;
+
+ /// Collection of program headers.
+ ProgramHeaderColl m_program_headers;
+
+ /// Collection of section headers.
+ SectionHeaderColl m_section_headers;
+
+ /// Collection of symbols from the dynamic table.
+ DynamicSymbolColl m_dynamic_symbols;
+
+ /// List of file specifications corresponding to the modules (shared
+ /// libraries) on which this object file depends.
+ mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
+
+ /// Cached value of the entry point for this module.
+ lldb_private::Address m_entry_point_address;
+
+ /// The architecture detected from parsing elf file contents.
+ lldb_private::ArchSpec m_arch_spec;
+
+ /// The address class for each symbol in the elf file
+ FileAddressToAddressClassMap m_address_class_map;
+
+ /// Returns a 1 based index of the given section header.
+ size_t SectionIndex(const SectionHeaderCollIter &I);
+
+ /// Returns a 1 based index of the given section header.
+ size_t SectionIndex(const SectionHeaderCollConstIter &I) const;
+
+ // Parses the ELF program headers.
+ static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
+ const SetDataFunction &set_data,
+ const elf::ELFHeader &header);
+
+ // Finds PT_NOTE segments and calculates their crc sum.
+ static uint32_t
+ CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl &program_headers,
+ lldb_private::DataExtractor &data);
+
+ /// Parses all section headers present in this object file and populates
+ /// m_program_headers. This method will compute the header list only once.
+ /// Returns the number of headers parsed.
+ size_t ParseProgramHeaders();
+
+ /// Parses all section headers present in this object file and populates
+ /// m_section_headers. This method will compute the header list only once.
+ /// Returns the number of headers parsed.
+ size_t ParseSectionHeaders();
+
+ static void ParseARMAttributes(lldb_private::DataExtractor &data,
+ uint64_t length,
+ lldb_private::ArchSpec &arch_spec);
+
+ /// Parses the elf section headers and returns the uuid, debug link name, crc,
+ /// archspec.
+ static size_t GetSectionHeaderInfo(SectionHeaderColl §ion_headers,
+ const SetDataFunction &set_data,
+ const elf::ELFHeader &header,
+ lldb_private::UUID &uuid,
+ std::string &gnu_debuglink_file,
+ uint32_t &gnu_debuglink_crc,
+ lldb_private::ArchSpec &arch_spec);
+
+ /// Scans the dynamic section and locates all dependent modules (shared
+ /// libraries) populating m_filespec_ap. This method will compute the
+ /// dependent module list only once. Returns the number of dependent
+ /// modules parsed.
+ size_t ParseDependentModules();
+
+ /// Parses the dynamic symbol table and populates m_dynamic_symbols. The
+ /// vector retains the order as found in the object file. Returns the
+ /// number of dynamic symbols parsed.
+ size_t ParseDynamicSymbols();
+
+ /// Populates m_symtab_ap will all non-dynamic linker symbols. This method
+ /// will parse the symbols only once. Returns the number of symbols parsed.
+ unsigned ParseSymbolTable(lldb_private::Symtab *symbol_table,
+ lldb::user_id_t start_id,
+ lldb_private::Section *symtab);
+
+ /// Helper routine for ParseSymbolTable().
+ unsigned ParseSymbols(lldb_private::Symtab *symbol_table,
+ lldb::user_id_t start_id,
+ lldb_private::SectionList *section_list,
+ const size_t num_symbols,
+ const lldb_private::DataExtractor &symtab_data,
+ const lldb_private::DataExtractor &strtab_data);
+
+ /// Scans the relocation entries and adds a set of artificial symbols to the
+ /// given symbol table for each PLT slot. Returns the number of symbols
+ /// added.
+ unsigned ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,
+ lldb::user_id_t start_id,
+ const ELFSectionHeaderInfo *rela_hdr,
+ lldb::user_id_t section_id);
+
+ void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,
+ lldb_private::DWARFCallFrameInfo *eh_frame);
+
+ /// Relocates debug sections
+ unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,
+ lldb::user_id_t rel_id);
+
+ unsigned RelocateSection(lldb_private::Symtab *symtab,
+ const elf::ELFHeader *hdr,
+ const elf::ELFSectionHeader *rel_hdr,
+ const elf::ELFSectionHeader *symtab_hdr,
+ const elf::ELFSectionHeader *debug_hdr,
+ lldb_private::DataExtractor &rel_data,
+ lldb_private::DataExtractor &symtab_data,
+ lldb_private::DataExtractor &debug_data,
+ lldb_private::Section *rel_section);
+
+ /// Loads the section name string table into m_shstr_data. Returns the
+ /// number of bytes constituting the table.
+ size_t GetSectionHeaderStringTable();
+
+ /// Utility method for looking up a section given its name. Returns the
+ /// index of the corresponding section or zero if no section with the given
+ /// name can be found (note that section indices are always 1 based, and so
+ /// section index 0 is never valid).
+ lldb::user_id_t GetSectionIndexByName(const char *name);
+
+ // Returns the ID of the first section that has the given type.
+ lldb::user_id_t GetSectionIndexByType(unsigned type);
+
+ /// Returns the section header with the given id or NULL.
+ const ELFSectionHeaderInfo *GetSectionHeaderByIndex(lldb::user_id_t id);
+
+ /// @name ELF header dump routines
+ //@{
+ static void DumpELFHeader(lldb_private::Stream *s,
+ const elf::ELFHeader &header);
+
+ static void DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,
+ unsigned char ei_data);
+
+ static void DumpELFHeader_e_type(lldb_private::Stream *s,
+ elf::elf_half e_type);
+ //@}
+
+ /// @name ELF program header dump routines
+ //@{
+ void DumpELFProgramHeaders(lldb_private::Stream *s);
+
+ static void DumpELFProgramHeader(lldb_private::Stream *s,
+ const elf::ELFProgramHeader &ph);
+
+ static void DumpELFProgramHeader_p_type(lldb_private::Stream *s,
+ elf::elf_word p_type);
+
+ static void DumpELFProgramHeader_p_flags(lldb_private::Stream *s,
+ elf::elf_word p_flags);
+ //@}
+
+ /// @name ELF section header dump routines
+ //@{
+ void DumpELFSectionHeaders(lldb_private::Stream *s);
+
+ static void DumpELFSectionHeader(lldb_private::Stream *s,
+ const ELFSectionHeaderInfo &sh);
+
+ static void DumpELFSectionHeader_sh_type(lldb_private::Stream *s,
+ elf::elf_word sh_type);
+
+ static void DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,
+ elf::elf_xword sh_flags);
+ //@}
+
+ /// ELF dependent module dump routine.
+ void DumpDependentModules(lldb_private::Stream *s);
+
+ const elf::ELFDynamic *FindDynamicSymbol(unsigned tag);
+
+ unsigned PLTRelocationType();
+
+ static lldb_private::Error
+ RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
+ lldb_private::ArchSpec &arch_spec,
+ lldb_private::UUID &uuid);
+
+ static lldb::offset_t SetData(const lldb_private::DataExtractor &src,
+ lldb_private::DataExtractor &dst,
+ lldb::offset_t offset, lldb::offset_t length);
+
+ lldb::offset_t SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst,
+ lldb::offset_t offset,
+ lldb::offset_t length);
};
#endif // liblldb_ObjectFileELF_h_
Modified: lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp Tue Sep 6 15:57:50 2016
@@ -26,8 +26,8 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/UUID.h"
-#include "lldb/Host/Host.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
@@ -41,322 +41,227 @@
using namespace lldb;
using namespace lldb_private;
+void ObjectFileJIT::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
-void
-ObjectFileJIT::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- CreateMemoryInstance,
- GetModuleSpecifications);
-}
-
-void
-ObjectFileJIT::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
-}
-
-
-lldb_private::ConstString
-ObjectFileJIT::GetPluginNameStatic()
-{
- static ConstString g_name("jit");
- return g_name;
-}
-
-const char *
-ObjectFileJIT::GetPluginDescriptionStatic()
-{
- return "JIT code object file";
-}
-
-ObjectFile *
-ObjectFileJIT::CreateInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const FileSpec* file,
- lldb::offset_t file_offset,
- lldb::offset_t length)
-{
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from a file
- return NULL;
-}
-
-ObjectFile *
-ObjectFileJIT::CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- DataBufferSP& data_sp,
- const ProcessSP &process_sp,
- lldb::addr_t header_addr)
-{
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from memory
- return NULL;
-}
-
-size_t
-ObjectFileJIT::GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs)
-{
- // JIT'ed object file can't be read from a file on disk
- return 0;
-}
-
-ObjectFileJIT::ObjectFileJIT (const lldb::ModuleSP &module_sp,
- const ObjectFileJITDelegateSP &delegate_sp) :
- ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0),
- m_delegate_wp ()
-{
- if (delegate_sp)
- {
- m_delegate_wp = delegate_sp;
- m_data.SetByteOrder(delegate_sp->GetByteOrder());
- m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
- }
+void ObjectFileJIT::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-ObjectFileJIT::~ObjectFileJIT()
-{
+lldb_private::ConstString ObjectFileJIT::GetPluginNameStatic() {
+ static ConstString g_name("jit");
+ return g_name;
}
+const char *ObjectFileJIT::GetPluginDescriptionStatic() {
+ return "JIT code object file";
+}
-bool
-ObjectFileJIT::ParseHeader ()
-{
- // JIT code is never in a file, nor is it required to have any header
- return false;
-}
-
-ByteOrder
-ObjectFileJIT::GetByteOrder () const
-{
- return m_data.GetByteOrder();
-}
-
-bool
-ObjectFileJIT::IsExecutable() const
-{
- return false;
-}
-
-uint32_t
-ObjectFileJIT::GetAddressByteSize () const
-{
- return m_data.GetAddressByteSize();
+ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
+ DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ const FileSpec *file,
+ lldb::offset_t file_offset,
+ lldb::offset_t length) {
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never
+ // read from a file
+ return NULL;
}
+ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
+ DataBufferSP &data_sp,
+ const ProcessSP &process_sp,
+ lldb::addr_t header_addr) {
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never
+ // read from memory
+ return NULL;
+}
-Symtab *
-ObjectFileJIT::GetSymtab()
-{
- ModuleSP module_sp(GetModule());
- if (module_sp)
- {
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- if (m_symtab_ap.get() == NULL)
- {
- m_symtab_ap.reset(new Symtab(this));
- std::lock_guard<std::recursive_mutex> symtab_guard(m_symtab_ap->GetMutex());
- ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
- if (delegate_sp)
- delegate_sp->PopulateSymtab(this, *m_symtab_ap);
- // TODO: get symbols from delegate
- m_symtab_ap->Finalize ();
- }
- }
- return m_symtab_ap.get();
+size_t ObjectFileJIT::GetModuleSpecifications(
+ const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, lldb::offset_t file_offset,
+ lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
+ // JIT'ed object file can't be read from a file on disk
+ return 0;
}
-bool
-ObjectFileJIT::IsStripped ()
-{
- return false; // JIT code that is in a module is never stripped
-}
-
-void
-ObjectFileJIT::CreateSections (SectionList &unified_section_list)
-{
- if (!m_sections_ap.get())
- {
- m_sections_ap.reset(new SectionList());
- ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
- if (delegate_sp)
- {
- delegate_sp->PopulateSectionList(this, *m_sections_ap);
- unified_section_list = *m_sections_ap;
- }
- }
+ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp,
+ const ObjectFileJITDelegateSP &delegate_sp)
+ : ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0), m_delegate_wp() {
+ if (delegate_sp) {
+ m_delegate_wp = delegate_sp;
+ m_data.SetByteOrder(delegate_sp->GetByteOrder());
+ m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
+ }
}
-void
-ObjectFileJIT::Dump (Stream *s)
-{
- ModuleSP module_sp(GetModule());
- if (module_sp)
- {
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- s->Printf("%p: ", static_cast<void*>(this));
- s->Indent();
- s->PutCString("ObjectFileJIT");
-
- ArchSpec arch;
- if (GetArchitecture(arch))
- *s << ", arch = " << arch.GetArchitectureName();
-
- s->EOL();
-
- SectionList *sections = GetSectionList();
- if (sections)
- sections->Dump(s, NULL, true, UINT32_MAX);
+ObjectFileJIT::~ObjectFileJIT() {}
- if (m_symtab_ap.get())
- m_symtab_ap->Dump(s, NULL, eSortOrderNone);
- }
+bool ObjectFileJIT::ParseHeader() {
+ // JIT code is never in a file, nor is it required to have any header
+ return false;
}
-bool
-ObjectFileJIT::GetUUID (lldb_private::UUID* uuid)
-{
- // TODO: maybe get from delegate, not needed for first pass
- return false;
-}
+ByteOrder ObjectFileJIT::GetByteOrder() const { return m_data.GetByteOrder(); }
+bool ObjectFileJIT::IsExecutable() const { return false; }
-uint32_t
-ObjectFileJIT::GetDependentModules (FileSpecList& files)
-{
- // JIT modules don't have dependencies, but they could
- // if external functions are called and we know where they are
- files.Clear();
- return 0;
+uint32_t ObjectFileJIT::GetAddressByteSize() const {
+ return m_data.GetAddressByteSize();
}
-lldb_private::Address
-ObjectFileJIT::GetEntryPointAddress ()
-{
- return Address();
+Symtab *ObjectFileJIT::GetSymtab() {
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ if (m_symtab_ap.get() == NULL) {
+ m_symtab_ap.reset(new Symtab(this));
+ std::lock_guard<std::recursive_mutex> symtab_guard(
+ m_symtab_ap->GetMutex());
+ ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
+ if (delegate_sp)
+ delegate_sp->PopulateSymtab(this, *m_symtab_ap);
+ // TODO: get symbols from delegate
+ m_symtab_ap->Finalize();
+ }
+ }
+ return m_symtab_ap.get();
}
-lldb_private::Address
-ObjectFileJIT::GetHeaderAddress ()
-{
- return Address();
+bool ObjectFileJIT::IsStripped() {
+ return false; // JIT code that is in a module is never stripped
}
+void ObjectFileJIT::CreateSections(SectionList &unified_section_list) {
+ if (!m_sections_ap.get()) {
+ m_sections_ap.reset(new SectionList());
+ ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
+ if (delegate_sp) {
+ delegate_sp->PopulateSectionList(this, *m_sections_ap);
+ unified_section_list = *m_sections_ap;
+ }
+ }
+}
+void ObjectFileJIT::Dump(Stream *s) {
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ s->Printf("%p: ", static_cast<void *>(this));
+ s->Indent();
+ s->PutCString("ObjectFileJIT");
-ObjectFile::Type
-ObjectFileJIT::CalculateType()
-{
- return eTypeJIT;
-}
+ ArchSpec arch;
+ if (GetArchitecture(arch))
+ *s << ", arch = " << arch.GetArchitectureName();
-ObjectFile::Strata
-ObjectFileJIT::CalculateStrata()
-{
- return eStrataJIT;
-}
+ s->EOL();
+ SectionList *sections = GetSectionList();
+ if (sections)
+ sections->Dump(s, NULL, true, UINT32_MAX);
-bool
-ObjectFileJIT::GetArchitecture (ArchSpec &arch)
-{
- ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock());
- if (delegate_sp)
- return delegate_sp->GetArchitecture(arch);
- return false;
+ if (m_symtab_ap.get())
+ m_symtab_ap->Dump(s, NULL, eSortOrderNone);
+ }
}
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-lldb_private::ConstString
-ObjectFileJIT::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ObjectFileJIT::GetPluginVersion()
-{
- return 1;
+bool ObjectFileJIT::GetUUID(lldb_private::UUID *uuid) {
+ // TODO: maybe get from delegate, not needed for first pass
+ return false;
}
+uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) {
+ // JIT modules don't have dependencies, but they could
+ // if external functions are called and we know where they are
+ files.Clear();
+ return 0;
+}
-bool
-ObjectFileJIT::SetLoadAddress (Target &target,
- lldb::addr_t value,
- bool value_is_offset)
-{
- size_t num_loaded_sections = 0;
- SectionList *section_list = GetSectionList ();
- if (section_list)
- {
- const size_t num_sections = section_list->GetSize();
- // "value" is an offset to apply to each top level segment
- for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx)
- {
- // Iterate through the object file sections to find all
- // of the sections that size on disk (to avoid __PAGEZERO)
- // and load them
- SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
- if (section_sp &&
- section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false)
- {
- if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value))
- ++num_loaded_sections;
- }
- }
- }
- return num_loaded_sections > 0;
+lldb_private::Address ObjectFileJIT::GetEntryPointAddress() {
+ return Address();
}
-
-size_t
-ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
- lldb::offset_t section_offset,
- void *dst,
- size_t dst_len) const
-{
- lldb::offset_t file_size = section->GetFileSize();
- if (section_offset < file_size)
- {
- size_t src_len = file_size - section_offset;
- if (src_len > dst_len)
- src_len = dst_len;
- const uint8_t *src = ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
-
- memcpy (dst, src, src_len);
- return src_len;
- }
- return 0;
+lldb_private::Address ObjectFileJIT::GetHeaderAddress() { return Address(); }
+
+ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; }
+
+ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; }
+
+bool ObjectFileJIT::GetArchitecture(ArchSpec &arch) {
+ ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
+ if (delegate_sp)
+ return delegate_sp->GetArchitecture(arch);
+ return false;
}
-size_t
-ObjectFileJIT::ReadSectionData (const lldb_private::Section *section,
- lldb_private::DataExtractor& section_data) const
-{
- if (section->GetFileSize())
- {
- const void *src = (void *)(uintptr_t)section->GetFileOffset();
-
- DataBufferSP data_sp (new lldb_private::DataBufferHeap(src, section->GetFileSize()));
- if (data_sp)
- {
- section_data.SetData (data_sp, 0, data_sp->GetByteSize());
- section_data.SetByteOrder (GetByteOrder());
- section_data.SetAddressByteSize (GetAddressByteSize());
- return section_data.GetByteSize();
- }
- }
- section_data.Clear();
- return 0;
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString ObjectFileJIT::GetPluginName() {
+ return GetPluginNameStatic();
}
+uint32_t ObjectFileJIT::GetPluginVersion() { return 1; }
+
+bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
+ bool value_is_offset) {
+ size_t num_loaded_sections = 0;
+ SectionList *section_list = GetSectionList();
+ if (section_list) {
+ const size_t num_sections = section_list->GetSize();
+ // "value" is an offset to apply to each top level segment
+ for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+ // Iterate through the object file sections to find all
+ // of the sections that size on disk (to avoid __PAGEZERO)
+ // and load them
+ SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
+ if (section_sp && section_sp->GetFileSize() > 0 &&
+ section_sp->IsThreadSpecific() == false) {
+ if (target.GetSectionLoadList().SetSectionLoadAddress(
+ section_sp, section_sp->GetFileAddress() + value))
+ ++num_loaded_sections;
+ }
+ }
+ }
+ return num_loaded_sections > 0;
+}
+
+size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section,
+ lldb::offset_t section_offset, void *dst,
+ size_t dst_len) const {
+ lldb::offset_t file_size = section->GetFileSize();
+ if (section_offset < file_size) {
+ size_t src_len = file_size - section_offset;
+ if (src_len > dst_len)
+ src_len = dst_len;
+ const uint8_t *src =
+ ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
+
+ memcpy(dst, src, src_len);
+ return src_len;
+ }
+ return 0;
+}
+
+size_t ObjectFileJIT::ReadSectionData(
+ const lldb_private::Section *section,
+ lldb_private::DataExtractor §ion_data) const {
+ if (section->GetFileSize()) {
+ const void *src = (void *)(uintptr_t)section->GetFileOffset();
+
+ DataBufferSP data_sp(
+ new lldb_private::DataBufferHeap(src, section->GetFileSize()));
+ if (data_sp) {
+ section_data.SetData(data_sp, 0, data_sp->GetByteSize());
+ section_data.SetByteOrder(GetByteOrder());
+ section_data.SetAddressByteSize(GetAddressByteSize());
+ return section_data.GetByteSize();
+ }
+ }
+ section_data.Clear();
+ return 0;
+}
Modified: lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h?rev=280751&r1=280750&r2=280751&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h (original)
+++ lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h Tue Sep 6 15:57:50 2016
@@ -21,126 +21,93 @@
// This class needs to be hidden as eventually belongs in a plugin that
// will export the ObjectFile protocol
//----------------------------------------------------------------------
-class ObjectFileJIT :
- public lldb_private::ObjectFile
-{
+class ObjectFileJIT : public lldb_private::ObjectFile {
public:
- ObjectFileJIT(const lldb::ModuleSP &module_sp,
- const lldb::ObjectFileJITDelegateSP &delegate_sp);
+ ObjectFileJIT(const lldb::ModuleSP &module_sp,
+ const lldb::ObjectFileJITDelegateSP &delegate_sp);
- ~ObjectFileJIT() override;
+ ~ObjectFileJIT() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ConstString
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::ObjectFile *
- CreateInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec* file,
- lldb::offset_t file_offset,
- lldb::offset_t length);
-
- static lldb_private::ObjectFile *
- CreateMemoryInstance (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- const lldb::ProcessSP &process_sp,
- lldb::addr_t header_addr);
-
- static size_t
- GetModuleSpecifications (const lldb_private::FileSpec& file,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- lldb::offset_t file_offset,
- lldb::offset_t length,
- lldb_private::ModuleSpecList &specs);
-
- //------------------------------------------------------------------
- // Member Functions
- //------------------------------------------------------------------
- bool
- ParseHeader() override;
-
- bool
- SetLoadAddress(lldb_private::Target &target,
- lldb::addr_t value,
- bool value_is_offset) override;
-
- lldb::ByteOrder
- GetByteOrder() const override;
-
- bool
- IsExecutable() const override;
-
- uint32_t
- GetAddressByteSize() const override;
-
- lldb_private::Symtab *
- GetSymtab() override;
-
- bool
- IsStripped() override;
-
- void
- CreateSections(lldb_private::SectionList &unified_section_list) override;
-
- void
- Dump(lldb_private::Stream *s) override;
-
- bool
- GetArchitecture(lldb_private::ArchSpec &arch) override;
-
- bool
- GetUUID(lldb_private::UUID* uuid) override;
-
- uint32_t
- GetDependentModules(lldb_private::FileSpecList& files) override;
-
- size_t
- ReadSectionData(const lldb_private::Section *section,
- lldb::offset_t section_offset,
- void *dst,
- size_t dst_len) const override;
-
- size_t
- ReadSectionData(const lldb_private::Section *section,
- lldb_private::DataExtractor& section_data) const override;
-
- lldb_private::Address
- GetEntryPointAddress() override;
-
- lldb_private::Address
- GetHeaderAddress() override;
-
- ObjectFile::Type
- CalculateType() override;
-
- ObjectFile::Strata
- CalculateStrata() override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- uint32_t
- GetPluginVersion() override;
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static lldb_private::ObjectFile *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const lldb_private::FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length);
+
+ static lldb_private::ObjectFile *CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+ static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
+
+ //------------------------------------------------------------------
+ // Member Functions
+ //------------------------------------------------------------------
+ bool ParseHeader() override;
+
+ bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,
+ bool value_is_offset) override;
+
+ lldb::ByteOrder GetByteOrder() const override;
+
+ bool IsExecutable() const override;
+
+ uint32_t GetAddressByteSize() const override;
+
+ lldb_private::Symtab *GetSymtab() override;
+
+ bool IsStripped() override;
+
+ void CreateSections(lldb_private::SectionList &unified_section_list) override;
+
+ void Dump(lldb_private::Stream *s) override;
+
+ bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+
+ bool GetUUID(lldb_private::UUID *uuid) override;
+
+ uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
+
+ size_t ReadSectionData(const lldb_private::Section *section,
+ lldb::offset_t section_offset, void *dst,
+ size_t dst_len) const override;
+
+ size_t
+ ReadSectionData(const lldb_private::Section *section,
+ lldb_private::DataExtractor §ion_data) const override;
+
+ lldb_private::Address GetEntryPointAddress() override;
+
+ lldb_private::Address GetHeaderAddress() override;
+
+ ObjectFile::Type CalculateType() override;
+
+ ObjectFile::Strata CalculateStrata() override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
protected:
- lldb::ObjectFileJITDelegateWP m_delegate_wp;
+ lldb::ObjectFileJITDelegateWP m_delegate_wp;
};
#endif // liblldb_ObjectFileJIT_h_
More information about the lldb-commits
mailing list