[llvm-branch-commits] [lldb] r183468 - Update platform branch with top of tree.
Greg Clayton
gclayton at apple.com
Thu Jun 6 17:08:11 PDT 2013
Modified: lldb/branches/lldb-platform-work/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/IRForTarget.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Expression/IRForTarget.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/IRForTarget.cpp Thu Jun 6 19:06:43 2013
@@ -10,22 +10,26 @@
#include "lldb/Expression/IRForTarget.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Constants.h"
-#include "llvm/InstrTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/ValueSymbolTable.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/IR/ValueSymbolTable.h"
#include "clang/AST/ASTContext.h"
-#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -36,32 +40,42 @@ using namespace llvm;
static char ID;
-IRForTarget::StaticDataAllocator::StaticDataAllocator()
+IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) :
+ m_execution_unit(execution_unit),
+ m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()),
+ m_allocation(LLDB_INVALID_ADDRESS)
{
}
-IRForTarget::StaticDataAllocator::~StaticDataAllocator()
+lldb::addr_t IRForTarget::StaticDataAllocator::Allocate()
{
+ lldb_private::Error err;
+
+ if (m_allocation != LLDB_INVALID_ADDRESS)
+ {
+ m_execution_unit.FreeNow(m_allocation);
+ m_allocation = LLDB_INVALID_ADDRESS;
+ }
+
+ m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err);
+
+ return m_allocation;
}
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
- lldb_private::ExecutionPolicy execution_policy,
- lldb::ClangExpressionVariableSP &const_result,
- StaticDataAllocator *data_allocator,
+ lldb_private::IRExecutionUnit &execution_unit,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
m_resolve_vars(resolve_vars),
- m_execution_policy(execution_policy),
- m_interpret_success(false),
m_func_name(func_name),
m_module(NULL),
m_decl_map(decl_map),
- m_data_allocator(data_allocator),
+ m_data_allocator(execution_unit),
+ m_memory_map(execution_unit),
m_CFStringCreateWithBytes(NULL),
m_sel_registerName(NULL),
- m_const_result(const_result),
m_error_stream(error_stream),
m_has_side_effects(false),
m_result_store(NULL),
@@ -76,11 +90,14 @@ static std::string
PrintValue(const Value *value, bool truncate = false)
{
std::string s;
- raw_string_ostream rso(s);
- value->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
+ if (value)
+ {
+ raw_string_ostream rso(s);
+ value->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ }
return s;
}
@@ -103,8 +120,6 @@ IRForTarget::~IRForTarget()
bool
IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
llvm_function.setLinkage(GlobalValue::ExternalLinkage);
std::string name = llvm_function.getName().str();
@@ -179,7 +194,7 @@ IRForTarget::GetFunctionAddress (llvm::F
lldb_private::ConstString &name,
Constant **&value_ptr)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
fun_addr = LLDB_INVALID_ADDRESS;
name.Clear();
@@ -236,7 +251,7 @@ IRForTarget::GetFunctionAddress (llvm::F
// Check for an alternate mangling for "std::basic_string<char>"
// that is part of the itanium C++ name mangling scheme
const char *name_cstr = name.GetCString();
- if (strncmp(name_cstr, "_ZNKSbIcE", strlen("_ZNKSbIcE")) == 0)
+ if (name_cstr && strncmp(name_cstr, "_ZNKSbIcE", strlen("_ZNKSbIcE")) == 0)
{
std::string alternate_mangling("_ZNKSs");
alternate_mangling.append (name_cstr + strlen("_ZNKSbIcE"));
@@ -266,6 +281,10 @@ IRForTarget::GetFunctionAddress (llvm::F
m_error_stream->Printf("error: call to a function '%s' (alternate name '%s') that is not present in the target\n",
mangled_name.GetName().GetCString(),
alt_mangled_name.GetName().GetCString());
+ else if (mangled_name.GetMangledName())
+ m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n",
+ mangled_name.GetName().GetCString(),
+ mangled_name.GetMangledName().GetCString());
else
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
mangled_name.GetName().GetCString());
@@ -289,7 +308,7 @@ IRForTarget::GetFunctionAddress (llvm::F
}
if (log)
- log->Printf("Found \"%s\" at 0x%llx", name.GetCString(), fun_addr);
+ log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr);
return true;
}
@@ -310,8 +329,6 @@ IRForTarget::RegisterFunctionMetadata(LL
llvm::Value *function_ptr,
const char *name)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
for (Value::use_iterator i = function_ptr->use_begin(), e = function_ptr->use_end();
i != e;
++i)
@@ -320,12 +337,10 @@ IRForTarget::RegisterFunctionMetadata(LL
if (Instruction *user_inst = dyn_cast<Instruction>(user))
{
- Constant *name_array = ConstantDataArray::getString(context, StringRef(name));
-
- ArrayRef<Value *> md_values(name_array);
-
- MDNode *metadata = MDNode::get(context, md_values);
-
+ MDString* md_name = MDString::get(context, StringRef(name));
+
+ MDNode *metadata = MDNode::get(context, md_name);
+
user_inst->setMetadata("lldb.call.realName", metadata);
}
else
@@ -339,7 +354,7 @@ bool
IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
llvm::Function &llvm_function)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
for (llvm::Module::iterator fi = llvm_module.begin();
fi != llvm_module.end();
@@ -385,8 +400,6 @@ IRForTarget::ResolveFunctionPointers(llv
clang::NamedDecl *
IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
if (!named_metadata)
@@ -429,98 +442,10 @@ IRForTarget::DeclForGlobal (GlobalValue
return DeclForGlobal(global_val, m_module);
}
-void
-IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
- const lldb_private::ConstString &name,
- lldb_private::TypeFromParser type)
-{
- if (llvm::ConstantExpr *init_expr = dyn_cast<llvm::ConstantExpr>(initializer))
- {
- switch (init_expr->getOpcode())
- {
- default:
- return;
- case Instruction::IntToPtr:
- MaybeSetConstantResult (init_expr->getOperand(0), name, type);
- return;
- }
- }
- else if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
- {
- m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
- }
-}
-
-void
-IRForTarget::MaybeSetCastResult (lldb_private::TypeFromParser type)
-{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_result_store)
- return;
-
- LoadInst *original_load = NULL;
-
- for (llvm::Value *current_value = m_result_store->getValueOperand(), *next_value;
- current_value != NULL;
- current_value = next_value)
- {
- CastInst *cast_inst = dyn_cast<CastInst>(current_value);
- LoadInst *load_inst = dyn_cast<LoadInst>(current_value);
-
- if (cast_inst)
- {
- next_value = cast_inst->getOperand(0);
- }
- else if (load_inst)
- {
- if (isa<LoadInst>(load_inst->getPointerOperand()))
- {
- next_value = load_inst->getPointerOperand();
- }
- else
- {
- original_load = load_inst;
- break;
- }
- }
- else
- {
- return;
- }
- }
-
- Value *loaded_value = original_load->getPointerOperand();
- GlobalVariable *loaded_global = dyn_cast<GlobalVariable>(loaded_value);
-
- if (!loaded_global)
- return;
-
- clang::NamedDecl *loaded_decl = DeclForGlobal(loaded_global);
-
- if (!loaded_decl)
- return;
-
- clang::VarDecl *loaded_var = dyn_cast<clang::VarDecl>(loaded_decl);
-
- if (!loaded_var)
- return;
-
- if (log)
- {
- lldb_private::StreamString type_desc_stream;
- type.DumpTypeDescription(&type_desc_stream);
-
- log->Printf("Type to cast variable to: \"%s\"", type_desc_stream.GetString().c_str());
- }
-
- m_const_result = m_decl_map->BuildCastVariable(m_result_name, loaded_var, type);
-}
-
bool
IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (!m_resolve_vars)
return true;
@@ -540,7 +465,7 @@ IRForTarget::CreateResultVariable (llvm:
const char *value_name = result_name_str.c_str();
if (strstr(value_name, "$__lldb_expr_result_ptr") &&
- !strstr(value_name, "GV"))
+ strncmp(value_name, "_ZGV", 4))
{
result_name = value_name;
m_result_is_pointer = true;
@@ -548,7 +473,7 @@ IRForTarget::CreateResultVariable (llvm:
}
if (strstr(value_name, "$__lldb_expr_result") &&
- !strstr(value_name, "GV"))
+ strncmp(value_name, "_ZGV", 4))
{
result_name = value_name;
m_result_is_pointer = false;
@@ -696,10 +621,10 @@ IRForTarget::CreateResultVariable (llvm:
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
}
- m_result_name = m_decl_map->GetPersistentResultName();
+ m_result_name = lldb_private::ConstString("$RESULT_NAME");
if (log)
- log->Printf("Creating a new result global: \"%s\" with size 0x%x",
+ log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
m_result_name.GetCString(),
m_result_type.GetClangTypeBitWidth() / 8);
@@ -788,22 +713,21 @@ IRForTarget::CreateResultVariable (llvm:
result_global->replaceAllUsesWith(new_result_global);
}
-
- if (!m_const_result)
- if (!m_decl_map->AddPersistentVariable(result_decl,
- m_result_name,
- m_result_type,
- true,
- m_result_is_pointer))
- return false;
+ if (!m_decl_map->AddPersistentVariable(result_decl,
+ m_result_name,
+ m_result_type,
+ true,
+ m_result_is_pointer))
+ return false;
+
result_global->eraseFromParent();
return true;
}
#if 0
-static void DebugUsers(lldb::LogSP &log, Value *value, uint8_t depth)
+static void DebugUsers(Log *log, Value *value, uint8_t depth)
{
if (!depth)
return;
@@ -832,13 +756,14 @@ IRForTarget::RewriteObjCConstString (llv
llvm::GlobalVariable *cstr,
Instruction *FirstEntryInstruction)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Type *ns_str_ty = ns_str->getType();
Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
- (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
+ (m_module->getPointerSize()
+ == Module::Pointer64) ? 64 : 32);
Type *i32_ty = Type::getInt32Ty(m_module->getContext());
Type *i8_ty = Type::getInt8Ty(m_module->getContext());
@@ -860,7 +785,7 @@ IRForTarget::RewriteObjCConstString (llv
}
if (log)
- log->Printf("Found CFStringCreateWithBytes at 0x%llx", CFStringCreateWithBytes_addr);
+ log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr);
// Build the function type:
//
@@ -944,7 +869,7 @@ IRForTarget::RewriteObjCConstString (llv
bool
IRForTarget::RewriteObjCConstStrings(Function &llvm_function)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
@@ -1187,7 +1112,7 @@ static bool IsObjCSelectorRef (Value *va
bool
IRForTarget::RewriteObjCSelector (Instruction* selector_load)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
LoadInst *load = dyn_cast<LoadInst>(selector_load);
@@ -1253,7 +1178,7 @@ IRForTarget::RewriteObjCSelector (Instru
return false;
if (log)
- log->Printf("Found sel_registerName at 0x%llx", sel_registerName_addr);
+ log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr);
// Build the function type: struct objc_selector *sel_registerName(uint8_t*)
@@ -1303,7 +1228,7 @@ IRForTarget::RewriteObjCSelector (Instru
bool
IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
BasicBlock::iterator ii;
@@ -1348,7 +1273,7 @@ IRForTarget::RewriteObjCSelectors (Basic
bool
IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
@@ -1419,7 +1344,7 @@ IRForTarget::RewritePersistentAllocs(llv
if (!m_resolve_vars)
return true;
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
BasicBlock::iterator ii;
@@ -1484,7 +1409,7 @@ IRForTarget::MaterializeInitializer (uin
if (!initializer)
return true;
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log && log->GetVerbose())
log->Printf(" MaterializeInitializer(%p, %s)", data, PrintValue(initializer).c_str());
@@ -1538,6 +1463,11 @@ IRForTarget::MaterializeInitializer (uin
}
return true;
}
+ else if (isa<ConstantAggregateZero>(initializer))
+ {
+ memset(data, 0, m_target_data->getTypeStoreSize(initializer_type));
+ return true;
+ }
return false;
}
@@ -1550,7 +1480,7 @@ IRForTarget::MaterializeInternalVariable
if (global_variable == m_reloc_placeholder)
return true;
- uint64_t offset = m_data_allocator->GetStream().GetSize();
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
llvm::Type *variable_type = global_variable->getType();
@@ -1563,7 +1493,7 @@ IRForTarget::MaterializeInternalVariable
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator->GetStream().PutNHex8(aligned_offset - offset, 0);
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
offset = aligned_offset;
lldb_private::DataBufferHeap data(size, '\0');
@@ -1572,7 +1502,7 @@ IRForTarget::MaterializeInternalVariable
if (!MaterializeInitializer(data.GetBytes(), initializer))
return false;
- m_data_allocator->GetStream().Write(data.GetBytes(), data.GetByteSize());
+ m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize());
Constant *new_pointer = BuildRelocation(variable_type, offset);
@@ -1587,7 +1517,7 @@ IRForTarget::MaterializeInternalVariable
bool
IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str());
@@ -1665,11 +1595,11 @@ IRForTarget::MaybeHandleVariable (Value
value_type = global_variable->getType();
}
- size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
- off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
+ uint64_t value_size = (ast_context->getTypeSize(qual_type) + 7ull) / 8ull;
+ off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7ull) / 8ull;
if (log)
- log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %lu, align %lld]",
+ log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRId64 "]",
name.c_str(),
qual_type.getAsString().c_str(),
PrintType(value_type).c_str(),
@@ -1685,6 +1615,8 @@ IRForTarget::MaybeHandleVariable (Value
{
if (!global_variable->hasExternalLinkage())
return true;
+ else if (HandleSymbol (global_variable))
+ return true;
else
return false;
}
@@ -1704,7 +1636,7 @@ IRForTarget::MaybeHandleVariable (Value
bool
IRForTarget::HandleSymbol (Value *symbol)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
lldb_private::ConstString name(symbol->getName().str().c_str());
@@ -1719,10 +1651,9 @@ IRForTarget::HandleSymbol (Value *symbol
}
if (log)
- log->Printf("Found \"%s\" at 0x%llx", name.GetCString(), symbol_addr);
+ log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr);
Type *symbol_type = symbol->getType();
-
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
(m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
@@ -1741,7 +1672,7 @@ IRForTarget::HandleSymbol (Value *symbol
bool
IRForTarget::MaybeHandleCallArguments (CallInst *Old)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str());
@@ -1763,7 +1694,7 @@ IRForTarget::MaybeHandleCallArguments (C
bool
IRForTarget::HandleObjCClass(Value *classlist_reference)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference);
@@ -1791,28 +1722,33 @@ IRForTarget::HandleObjCClass(Value *clas
if (global_variable->use_begin() == global_variable->use_end())
return false;
- LoadInst *load_instruction = NULL;
-
+ SmallVector<LoadInst *, 2> load_instructions;
+
for (Value::use_iterator i = global_variable->use_begin(), e = global_variable->use_end();
i != e;
++i)
{
- if ((load_instruction = dyn_cast<LoadInst>(*i)))
- break;
+ if (LoadInst *load_instruction = dyn_cast<LoadInst>(*i))
+ load_instructions.push_back(load_instruction);
}
- if (!load_instruction)
+ if (load_instructions.empty())
return false;
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
- (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
+ (m_module->getPointerSize()
+ == Module::Pointer64) ? 64 : 32);
Constant *class_addr = ConstantInt::get(intptr_ty, (uint64_t)class_ptr);
- Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
- load_instruction->replaceAllUsesWith(class_bitcast);
+ for (LoadInst *load_instruction : load_instructions)
+ {
+ Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
- load_instruction->eraseFromParent();
+ load_instruction->replaceAllUsesWith(class_bitcast);
+
+ load_instruction->eraseFromParent();
+ }
return true;
}
@@ -1890,7 +1826,7 @@ IRForTarget::ResolveCalls(BasicBlock &ba
bool
IRForTarget::ResolveExternals (Function &llvm_function)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
for (Module::global_iterator global = m_module->global_begin(), end = m_module->global_end();
global != end;
@@ -1931,6 +1867,16 @@ IRForTarget::ResolveExternals (Function
return false;
}
}
+ else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos)
+ {
+ if (!HandleObjCClass(global))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
+
+ return false;
+ }
+ }
else if (DeclForGlobal(global))
{
if (!MaybeHandleVariable (global))
@@ -1949,10 +1895,7 @@ IRForTarget::ResolveExternals (Function
bool
IRForTarget::ReplaceStrings ()
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_data_allocator)
- return true; // hope for the best; some clients may not want static allocation!
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
typedef std::map <GlobalVariable *, size_t> OffsetsTy;
@@ -2005,9 +1948,9 @@ IRForTarget::ReplaceStrings ()
str = gc_array->getAsString();
}
- offsets[gv] = m_data_allocator->GetStream().GetSize();
+ offsets[gv] = m_data_allocator.GetStream().GetSize();
- m_data_allocator->GetStream().Write(str.c_str(), str.length() + 1);
+ m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1);
}
Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
@@ -2073,10 +2016,7 @@ IRForTarget::ReplaceStrings ()
bool
IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (!m_data_allocator)
- return true;
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
typedef SmallVector <Value*, 2> ConstantList;
typedef SmallVector <llvm::Instruction*, 2> UserList;
@@ -2119,10 +2059,11 @@ IRForTarget::ReplaceStaticLiterals (llvm
llvm::Instruction *inst = *user_iter;
ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
- Type *operand_type = operand_constant_fp->getType();
if (operand_constant_fp)
{
+ Type *operand_type = operand_constant_fp->getType();
+
APFloat operand_apfloat = operand_constant_fp->getValueAPF();
APInt operand_apint = operand_apfloat.bitcastToAPInt();
@@ -2147,7 +2088,7 @@ IRForTarget::ReplaceStaticLiterals (llvm
lldb_private::DataBufferHeap data(operand_data_size, 0);
- if (lldb::endian::InlHostByteOrder() != m_data_allocator->GetStream().GetByteOrder())
+ if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
{
uint8_t *data_bytes = data.GetBytes();
@@ -2163,20 +2104,20 @@ IRForTarget::ReplaceStaticLiterals (llvm
memcpy(data.GetBytes(), operand_raw_data, operand_data_size);
}
- uint64_t offset = m_data_allocator->GetStream().GetSize();
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
size_t align = m_target_data->getPrefTypeAlignment(operand_type);
const size_t mask = (align - 1);
uint64_t aligned_offset = (offset + mask) & ~mask;
- m_data_allocator->GetStream().PutNHex8(aligned_offset - offset, 0);
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
offset = aligned_offset;
- m_data_allocator->GetStream().Write(data.GetBytes(), operand_data_size);
+ m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size);
llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
- Constant *new_pointer = BuildRelocation(fp_ptr_ty, offset);
+ Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset);
llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst);
@@ -2290,7 +2231,7 @@ IRForTarget::RemoveGuards(BasicBlock &ba
bool
IRForTarget::UnfoldConstant(Constant *old_constant, Value *new_constant, Instruction *first_entry_inst)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Value::use_iterator ui;
@@ -2396,7 +2337,7 @@ IRForTarget::ReplaceVariables (Function
if (!m_resolve_vars)
return true;
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
m_decl_map->DoStructLayout();
@@ -2520,7 +2461,7 @@ IRForTarget::ReplaceVariables (Function
}
if (log)
- log->Printf(" \"%s\" (\"%s\") placed at %lld",
+ log->Printf(" \"%s\" (\"%s\") placed at %" PRId64,
name.GetCString(),
decl->getNameAsString().c_str(),
offset);
@@ -2564,17 +2505,14 @@ IRForTarget::ReplaceVariables (Function
}
if (log)
- log->Printf("Total structure [align %lld, size %lu]", alignment, size);
+ log->Printf("Total structure [align %" PRId64 ", size %lu]", alignment, size);
return true;
}
llvm::Constant *
-IRForTarget::BuildRelocation(llvm::Type *type,
- uint64_t offset)
+IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
(m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
@@ -2594,16 +2532,13 @@ IRForTarget::BuildRelocation(llvm::Type
bool
IRForTarget::CompleteDataAllocation ()
-{
- if (!m_data_allocator)
- return true;
-
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (!m_data_allocator->GetStream().GetSize())
+ if (!m_data_allocator.GetStream().GetSize())
return true;
- lldb::addr_t allocation = m_data_allocator->Allocate();
+ lldb::addr_t allocation = m_data_allocator.Allocate();
if (log)
{
@@ -2613,7 +2548,7 @@ IRForTarget::CompleteDataAllocation ()
log->Printf("Failed to allocate static data");
}
- if (!allocation)
+ if (!allocation || allocation == LLDB_INVALID_ADDRESS)
return false;
IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
@@ -2630,12 +2565,62 @@ IRForTarget::CompleteDataAllocation ()
}
bool
+IRForTarget::StripAllGVs (Module &llvm_module)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ std::vector<GlobalVariable *> global_vars;
+ std::set<GlobalVariable *>erased_vars;
+
+ bool erased = true;
+
+ while (erased)
+ {
+ erased = false;
+
+ for (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end();
+ gi != ge;
+ ++gi)
+ {
+ GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi);
+
+ global_var->removeDeadConstantUsers();
+
+ if (global_var->use_empty())
+ {
+ if (log)
+ log->Printf("Did remove %s",
+ PrintValue(global_var).c_str());
+ global_var->eraseFromParent();
+ erased = true;
+ break;
+ }
+ }
+ }
+
+ for (Module::global_iterator gi = llvm_module.global_begin(), ge = llvm_module.global_end();
+ gi != ge;
+ ++gi)
+ {
+ GlobalVariable *global_var = dyn_cast<GlobalVariable>(gi);
+
+ GlobalValue::use_iterator ui = global_var->use_begin();
+
+ if (log)
+ log->Printf("Couldn't remove %s because of %s",
+ PrintValue(global_var).c_str(),
+ PrintValue(*ui).c_str());
+ }
+
+ return true;
+}
+
+bool
IRForTarget::runOnModule (Module &llvm_module)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
m_module = &llvm_module;
- m_target_data.reset(new TargetData(m_module));
+ m_target_data.reset(new DataLayout(m_module));
Function* function = m_module->getFunction(StringRef(m_func_name.c_str()));
@@ -2674,12 +2659,12 @@ IRForTarget::runOnModule (Module &llvm_m
m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
intptr_ty,
- false /* isConstant */,
+ false /* IsConstant */,
GlobalVariable::InternalLinkage,
Constant::getNullValue(intptr_ty),
"reloc_placeholder",
NULL /* InsertBefore */,
- false /* ThreadLocal */,
+ GlobalVariable::NotThreadLocal /* ThreadLocal */,
0 /* AddressSpace */);
Function::iterator bbi;
@@ -2699,12 +2684,6 @@ IRForTarget::runOnModule (Module &llvm_m
return false;
}
-
- if (m_const_result && m_execution_policy != lldb_private::eExecutionPolicyAlways)
- {
- m_interpret_success = true;
- return true;
- }
for (bbi = function->begin();
bbi != function->end();
@@ -2741,23 +2720,6 @@ IRForTarget::runOnModule (Module &llvm_m
}
}
- if (m_decl_map && m_execution_policy != lldb_private::eExecutionPolicyAlways)
- {
- IRInterpreter interpreter (*m_decl_map,
- m_error_stream);
-
- interpreter.maybeRunOnFunction(m_const_result, m_result_name, m_result_type, *function, llvm_module, m_interpreter_error);
-
- if (m_interpreter_error.Success())
- return true;
- }
-
- if (m_execution_policy == lldb_private::eExecutionPolicyNever) {
- if (m_result_name)
- m_decl_map->RemoveResultVariable(m_result_name);
- return false;
- }
-
if (log && log->GetVerbose())
{
std::string s;
@@ -2876,6 +2838,12 @@ IRForTarget::runOnModule (Module &llvm_m
return false;
}
+ if (!StripAllGVs(llvm_module))
+ {
+ if (log)
+ log->Printf("StripAllGVs() failed");
+ }
+
if (log && log->GetVerbose())
{
std::string s;
Modified: lldb/branches/lldb-platform-work/source/Expression/IRInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/IRInterpreter.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Expression/IRInterpreter.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/IRInterpreter.cpp Thu Jun 6 19:06:43 2013
@@ -7,38 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
-#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/IRInterpreter.h"
-#include "llvm/Constants.h"
-#include "llvm/Function.h"
-#include "llvm/Instructions.h"
-#include "llvm/Module.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetData.h"
#include <map>
using namespace llvm;
-IRInterpreter::IRInterpreter(lldb_private::ClangExpressionDeclMap &decl_map,
- lldb_private::Stream *error_stream) :
- m_decl_map(decl_map),
- m_error_stream(error_stream)
-{
-
-}
-
-IRInterpreter::~IRInterpreter()
-{
-
-}
-
static std::string
PrintValue(const Value *value, bool truncate = false)
{
@@ -70,362 +57,42 @@ PrintType(const Type *type, bool truncat
return s;
}
-typedef STD_SHARED_PTR(lldb_private::DataEncoder) DataEncoderSP;
-typedef STD_SHARED_PTR(lldb_private::DataExtractor) DataExtractorSP;
-
-class Memory
-{
-public:
- typedef uint32_t index_t;
-
- struct Allocation
- {
- // m_virtual_address is always the address of the variable in the virtual memory
- // space provided by Memory.
- //
- // m_origin is always non-NULL and describes the source of the data (possibly
- // m_data if this allocation is the authoritative source).
- //
- // Possible value configurations:
- //
- // Allocation type getValueType() getContextType() m_origin->GetScalar() m_data
- // =========================================================================================================================
- // FileAddress eValueTypeFileAddress eContextTypeInvalid A location in a binary NULL
- // image
- //
- // LoadAddress eValueTypeLoadAddress eContextTypeInvalid A location in the target's NULL
- // virtual memory
- //
- // Alloca eValueTypeHostAddress eContextTypeInvalid == m_data->GetBytes() Deleted at end of
- // execution
- //
- // PersistentVar eValueTypeHostAddress eContextTypeClangType A persistent variable's NULL
- // location in LLDB's memory
- //
- // Register [ignored] eContextTypeRegister [ignored] Flushed to the register
- // at the end of execution
-
- lldb::addr_t m_virtual_address;
- size_t m_extent;
- lldb_private::Value m_origin;
- lldb::DataBufferSP m_data;
-
- Allocation (lldb::addr_t virtual_address,
- size_t extent,
- lldb::DataBufferSP data) :
- m_virtual_address(virtual_address),
- m_extent(extent),
- m_data(data)
- {
- }
-
- Allocation (const Allocation &allocation) :
- m_virtual_address(allocation.m_virtual_address),
- m_extent(allocation.m_extent),
- m_origin(allocation.m_origin),
- m_data(allocation.m_data)
- {
- }
- };
-
- typedef STD_SHARED_PTR(Allocation) AllocationSP;
-
- struct Region
- {
- AllocationSP m_allocation;
- uint64_t m_base;
- uint64_t m_extent;
-
- Region () :
- m_allocation(),
- m_base(0),
- m_extent(0)
- {
- }
-
- Region (AllocationSP allocation, uint64_t base, uint64_t extent) :
- m_allocation(allocation),
- m_base(base),
- m_extent(extent)
- {
- }
-
- Region (const Region ®ion) :
- m_allocation(region.m_allocation),
- m_base(region.m_base),
- m_extent(region.m_extent)
- {
- }
-
- bool IsValid ()
- {
- return (bool) m_allocation;
- }
-
- bool IsInvalid ()
- {
- return !m_allocation;
- }
- };
-
- typedef std::vector <AllocationSP> MemoryMap;
-
-private:
- lldb::addr_t m_addr_base;
- lldb::addr_t m_addr_max;
- MemoryMap m_memory;
- lldb::ByteOrder m_byte_order;
- lldb::addr_t m_addr_byte_size;
- TargetData &m_target_data;
-
- lldb_private::ClangExpressionDeclMap &m_decl_map;
-
- MemoryMap::iterator LookupInternal (lldb::addr_t addr)
- {
- for (MemoryMap::iterator i = m_memory.begin(), e = m_memory.end();
- i != e;
- ++i)
- {
- if ((*i)->m_virtual_address <= addr &&
- (*i)->m_virtual_address + (*i)->m_extent > addr)
- return i;
- }
-
- return m_memory.end();
- }
-
-public:
- Memory (TargetData &target_data,
- lldb_private::ClangExpressionDeclMap &decl_map,
- lldb::addr_t alloc_start,
- lldb::addr_t alloc_max) :
- m_addr_base(alloc_start),
- m_addr_max(alloc_max),
- m_target_data(target_data),
- m_decl_map(decl_map)
- {
- m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
- m_addr_byte_size = (target_data.getPointerSize());
- }
-
- Region Malloc (size_t size, size_t align)
- {
- lldb::DataBufferSP data(new lldb_private::DataBufferHeap(size, 0));
-
- if (data)
- {
- index_t index = m_memory.size();
-
- const size_t mask = (align - 1);
-
- m_addr_base += mask;
- m_addr_base &= ~mask;
-
- if (m_addr_base + size < m_addr_base ||
- m_addr_base + size > m_addr_max)
- return Region();
-
- uint64_t base = m_addr_base;
-
- m_memory.push_back(AllocationSP(new Allocation(base, size, data)));
-
- m_addr_base += size;
-
- AllocationSP alloc = m_memory[index];
-
- alloc->m_origin.GetScalar() = (unsigned long long)data->GetBytes();
- alloc->m_origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
- alloc->m_origin.SetValueType(lldb_private::Value::eValueTypeHostAddress);
-
- return Region(alloc, base, size);
- }
-
- return Region();
- }
-
- Region Malloc (Type *type)
- {
- return Malloc (m_target_data.getTypeAllocSize(type),
- m_target_data.getPrefTypeAlignment(type));
- }
-
- Region Place (Type *type, lldb::addr_t base, lldb_private::Value &value)
- {
- index_t index = m_memory.size();
- size_t size = m_target_data.getTypeAllocSize(type);
-
- m_memory.push_back(AllocationSP(new Allocation(base, size, lldb::DataBufferSP())));
-
- AllocationSP alloc = m_memory[index];
-
- alloc->m_origin = value;
-
- return Region(alloc, base, size);
- }
-
- void Free (lldb::addr_t addr)
- {
- MemoryMap::iterator i = LookupInternal (addr);
-
- if (i != m_memory.end())
- m_memory.erase(i);
- }
-
- Region Lookup (lldb::addr_t addr, Type *type)
- {
- MemoryMap::iterator i = LookupInternal(addr);
-
- if (i == m_memory.end() || !type->isSized())
- return Region();
-
- size_t size = m_target_data.getTypeStoreSize(type);
-
- return Region(*i, addr, size);
- }
-
- DataEncoderSP GetEncoder (Region region)
- {
- if (region.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress)
- return DataEncoderSP();
-
- lldb::DataBufferSP buffer = region.m_allocation->m_data;
-
- if (!buffer)
- return DataEncoderSP();
-
- size_t base_offset = (size_t)(region.m_base - region.m_allocation->m_virtual_address);
-
- return DataEncoderSP(new lldb_private::DataEncoder(buffer->GetBytes() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
- }
-
- DataExtractorSP GetExtractor (Region region)
- {
- if (region.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress)
- return DataExtractorSP();
-
- lldb::DataBufferSP buffer = region.m_allocation->m_data;
- size_t base_offset = (size_t)(region.m_base - region.m_allocation->m_virtual_address);
-
- if (buffer)
- return DataExtractorSP(new lldb_private::DataExtractor(buffer->GetBytes() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
- else
- return DataExtractorSP(new lldb_private::DataExtractor((uint8_t*)region.m_allocation->m_origin.GetScalar().ULongLong() + base_offset, region.m_extent, m_byte_order, m_addr_byte_size));
- }
-
- lldb_private::Value GetAccessTarget(lldb::addr_t addr)
- {
- MemoryMap::iterator i = LookupInternal(addr);
-
- if (i == m_memory.end())
- return lldb_private::Value();
-
- lldb_private::Value target = (*i)->m_origin;
-
- if (target.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo)
- {
- target.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
- target.SetValueType(lldb_private::Value::eValueTypeHostAddress);
- target.GetScalar() = (unsigned long long)(*i)->m_data->GetBytes();
- }
-
- target.GetScalar() += (addr - (*i)->m_virtual_address);
-
- return target;
- }
-
- bool Write (lldb::addr_t addr, const uint8_t *data, size_t length)
- {
- lldb_private::Value target = GetAccessTarget(addr);
-
- return m_decl_map.WriteTarget(target, data, length);
- }
-
- bool Read (uint8_t *data, lldb::addr_t addr, size_t length)
- {
- lldb_private::Value source = GetAccessTarget(addr);
-
- return m_decl_map.ReadTarget(data, source, length);
- }
-
- bool WriteToRawPtr (lldb::addr_t addr, const uint8_t *data, size_t length)
- {
- lldb_private::Value target = m_decl_map.WrapBareAddress(addr);
-
- return m_decl_map.WriteTarget(target, data, length);
- }
-
- bool ReadFromRawPtr (uint8_t *data, lldb::addr_t addr, size_t length)
- {
- lldb_private::Value source = m_decl_map.WrapBareAddress(addr);
-
- return m_decl_map.ReadTarget(data, source, length);
- }
-
- std::string PrintData (lldb::addr_t addr, size_t length)
- {
- lldb_private::Value target = GetAccessTarget(addr);
-
- lldb_private::DataBufferHeap buf(length, 0);
-
- if (!m_decl_map.ReadTarget(buf.GetBytes(), target, length))
- return std::string("<couldn't read data>");
-
- lldb_private::StreamString ss;
-
- for (size_t i = 0; i < length; i++)
- {
- if ((!(i & 0xf)) && i)
- ss.Printf("%02hhx - ", buf.GetBytes()[i]);
- else
- ss.Printf("%02hhx ", buf.GetBytes()[i]);
- }
-
- return ss.GetString();
- }
-
- std::string SummarizeRegion (Region ®ion)
- {
- lldb_private::StreamString ss;
-
- lldb_private::Value base = GetAccessTarget(region.m_base);
-
- ss.Printf("%llx [%s - %s %llx]",
- region.m_base,
- lldb_private::Value::GetValueTypeAsCString(base.GetValueType()),
- lldb_private::Value::GetContextTypeAsCString(base.GetContextType()),
- base.GetScalar().ULongLong());
-
- ss.Printf(" %s", PrintData(region.m_base, region.m_extent).c_str());
-
- return ss.GetString();
- }
-};
-
class InterpreterStackFrame
{
public:
- typedef std::map <const Value*, Memory::Region> ValueMap;
-
+ typedef std::map <const Value*, lldb::addr_t> ValueMap;
+
ValueMap m_values;
- Memory &m_memory;
- TargetData &m_target_data;
- lldb_private::ClangExpressionDeclMap &m_decl_map;
+ DataLayout &m_target_data;
+ lldb_private::IRMemoryMap &m_memory_map;
const BasicBlock *m_bb;
BasicBlock::const_iterator m_ii;
BasicBlock::const_iterator m_ie;
+ lldb::addr_t m_frame_process_address;
+ size_t m_frame_size;
+ lldb::addr_t m_stack_pointer;
+
lldb::ByteOrder m_byte_order;
size_t m_addr_byte_size;
- InterpreterStackFrame (TargetData &target_data,
- Memory &memory,
- lldb_private::ClangExpressionDeclMap &decl_map) :
- m_memory (memory),
+ InterpreterStackFrame (DataLayout &target_data,
+ lldb_private::IRMemoryMap &memory_map,
+ lldb::addr_t stack_frame_bottom,
+ lldb::addr_t stack_frame_top) :
m_target_data (target_data),
- m_decl_map (decl_map)
+ m_memory_map (memory_map)
{
m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
- m_addr_byte_size = (target_data.getPointerSize());
+ m_addr_byte_size = (target_data.getPointerSize(0));
+
+ m_frame_process_address = stack_frame_bottom;
+ m_frame_size = stack_frame_top - stack_frame_bottom;
+ m_stack_pointer = stack_frame_top;
+ }
+
+ ~InterpreterStackFrame ()
+ {
}
void Jump (const BasicBlock *bb)
@@ -435,14 +102,6 @@ public:
m_ie = m_bb->end();
}
- bool Cache (Memory::AllocationSP allocation, Type *type)
- {
- if (allocation->m_origin.GetContextType() != lldb_private::Value::eContextTypeRegisterInfo)
- return false;
-
- return m_decl_map.ReadTarget(allocation->m_data->GetBytes(), allocation->m_origin, allocation->m_data->GetByteSize());
- }
-
std::string SummarizeValue (const Value *value)
{
lldb_private::StreamString ss;
@@ -453,9 +112,9 @@ public:
if (i != m_values.end())
{
- Memory::Region region = i->second;
+ lldb::addr_t addr = i->second;
- ss.Printf(" %s", m_memory.SummarizeRegion(region).c_str());
+ ss.Printf(" 0x%llx", (unsigned long long)addr);
}
return ss.GetString();
@@ -492,25 +151,32 @@ public:
if (constant)
{
- if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
- {
- return AssignToMatchType(scalar, constant_int->getLimitedValue(), value->getType());
- }
+ APInt value_apint;
+
+ if (!ResolveConstantValue(value_apint, constant))
+ return false;
+
+ return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType());
}
else
{
- Memory::Region region = ResolveValue(value, module);
- DataExtractorSP value_extractor = m_memory.GetExtractor(region);
+ lldb::addr_t process_address = ResolveValue(value, module);
+ size_t value_size = m_target_data.getTypeStoreSize(value->getType());
+
+ lldb_private::DataExtractor value_extractor;
+ lldb_private::Error extract_error;
- if (!value_extractor)
+ m_memory_map.GetMemoryData(value_extractor, process_address, value_size, extract_error);
+
+ if (!extract_error.Success())
return false;
- size_t value_size = m_target_data.getTypeStoreSize(value->getType());
-
- uint32_t offset = 0;
- uint64_t u64value = value_extractor->GetMaxU64(&offset, value_size);
-
- return AssignToMatchType(scalar, u64value, value->getType());
+ lldb::offset_t offset = 0;
+ if (value_size == 1 || value_size == 2 || value_size == 4 || value_size == 8)
+ {
+ uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
+ return AssignToMatchType(scalar, u64value, value->getType());
+ }
}
return false;
@@ -518,415 +184,251 @@ public:
bool AssignValue (const Value *value, lldb_private::Scalar &scalar, Module &module)
{
- Memory::Region region = ResolveValue (value, module);
+ lldb::addr_t process_address = ResolveValue (value, module);
+
+ if (process_address == LLDB_INVALID_ADDRESS)
+ return false;
lldb_private::Scalar cast_scalar;
if (!AssignToMatchType(cast_scalar, scalar.GetRawBits64(0), value->getType()))
return false;
+
+ size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
- lldb_private::DataBufferHeap buf(cast_scalar.GetByteSize(), 0);
+ lldb_private::DataBufferHeap buf(value_byte_size, 0);
- lldb_private::Error err;
+ lldb_private::Error get_data_error;
- if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, err))
+ if (!cast_scalar.GetAsMemoryData(buf.GetBytes(), buf.GetByteSize(), m_byte_order, get_data_error))
return false;
- DataEncoderSP region_encoder = m_memory.GetEncoder(region);
+ lldb_private::Error write_error;
- memcpy(region_encoder->GetDataStart(), buf.GetBytes(), buf.GetByteSize());
+ m_memory_map.WriteMemory(process_address, buf.GetBytes(), buf.GetByteSize(), write_error);
- return true;
+ return write_error.Success();
}
bool ResolveConstantValue (APInt &value, const Constant *constant)
{
- if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
- {
- value = constant_int->getValue();
- return true;
- }
- else if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
- {
- value = constant_fp->getValueAPF().bitcastToAPInt();
- return true;
- }
- else if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+ switch (constant->getValueID())
{
- switch (constant_expr->getOpcode())
+ default:
+ break;
+ case Value::ConstantIntVal:
+ if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
{
- default:
- return false;
- case Instruction::IntToPtr:
- case Instruction::BitCast:
- return ResolveConstantValue(value, constant_expr->getOperand(0));
- case Instruction::GetElementPtr:
- {
- ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
- ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
-
- Constant *base = dyn_cast<Constant>(*op_cursor);
-
- if (!base)
- return false;
-
- if (!ResolveConstantValue(value, base))
+ value = constant_int->getValue();
+ return true;
+ }
+ break;
+ case Value::ConstantFPVal:
+ if (const ConstantFP *constant_fp = dyn_cast<ConstantFP>(constant))
+ {
+ value = constant_fp->getValueAPF().bitcastToAPInt();
+ return true;
+ }
+ break;
+ case Value::ConstantExprVal:
+ if (const ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+ {
+ switch (constant_expr->getOpcode())
+ {
+ default:
return false;
-
- op_cursor++;
-
- if (op_cursor == op_end)
- return true; // no offset to apply!
-
- SmallVector <Value *, 8> indices (op_cursor, op_end);
-
- uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices);
-
- const bool is_signed = true;
- value += APInt(value.getBitWidth(), offset, is_signed);
-
- return true;
+ case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
+ case Instruction::BitCast:
+ return ResolveConstantValue(value, constant_expr->getOperand(0));
+ case Instruction::GetElementPtr:
+ {
+ ConstantExpr::const_op_iterator op_cursor = constant_expr->op_begin();
+ ConstantExpr::const_op_iterator op_end = constant_expr->op_end();
+
+ Constant *base = dyn_cast<Constant>(*op_cursor);
+
+ if (!base)
+ return false;
+
+ if (!ResolveConstantValue(value, base))
+ return false;
+
+ op_cursor++;
+
+ if (op_cursor == op_end)
+ return true; // no offset to apply!
+
+ SmallVector <Value *, 8> indices (op_cursor, op_end);
+
+ uint64_t offset = m_target_data.getIndexedOffset(base->getType(), indices);
+
+ const bool is_signed = true;
+ value += APInt(value.getBitWidth(), offset, is_signed);
+
+ return true;
+ }
}
}
+ break;
+ case Value::ConstantPointerNullVal:
+ if (isa<ConstantPointerNull>(constant))
+ {
+ value = APInt(m_target_data.getPointerSizeInBits(), 0);
+ return true;
+ }
+ break;
}
-
return false;
}
- bool ResolveConstant (Memory::Region ®ion, const Constant *constant)
+ bool MakeArgument(const Argument *value, uint64_t address)
{
- APInt resolved_value;
+ lldb::addr_t data_address = Malloc(value->getType());
- if (!ResolveConstantValue(resolved_value, constant))
+ if (data_address == LLDB_INVALID_ADDRESS)
return false;
- const uint64_t *raw_data = resolved_value.getRawData();
-
- size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
- return m_memory.Write(region.m_base, (const uint8_t*)raw_data, constant_size);
- }
+ lldb_private::Error write_error;
- Memory::Region ResolveValue (const Value *value, Module &module)
- {
- ValueMap::iterator i = m_values.find(value);
+ m_memory_map.WritePointerToMemory(data_address, address, write_error);
- if (i != m_values.end())
- return i->second;
+ if (!write_error.Success())
+ {
+ lldb_private::Error free_error;
+ m_memory_map.Free(data_address, free_error);
+ return false;
+ }
- const GlobalValue *global_value = dyn_cast<GlobalValue>(value);
+ m_values[value] = data_address;
- // If the variable is indirected through the argument
- // array then we need to build an extra level of indirection
- // for it. This is the default; only magic arguments like
- // "this", "self", and "_cmd" are direct.
- bool indirect_variable = true;
-
- // Attempt to resolve the value using the program's data.
- // If it is, the values to be created are:
- //
- // data_region - a region of memory in which the variable's data resides.
- // ref_region - a region of memory in which its address (i.e., &var) resides.
- // In the JIT case, this region would be a member of the struct passed in.
- // pointer_region - a region of memory in which the address of the pointer
- // resides. This is an IR-level variable.
- do
- {
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- lldb_private::Value resolved_value;
- lldb_private::ClangExpressionVariable::FlagType flags = 0;
-
- if (global_value)
- {
- clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
-
- if (!decl)
- break;
-
- if (isa<clang::FunctionDecl>(decl))
- {
- if (log)
- log->Printf("The interpreter does not handle function pointers at the moment");
-
- return Memory::Region();
- }
-
- resolved_value = m_decl_map.LookupDecl(decl, flags);
- }
- else
- {
- // Special-case "this", "self", and "_cmd"
-
- std::string name_str = value->getName().str();
-
- if (name_str == "this" ||
- name_str == "self" ||
- name_str == "_cmd")
- resolved_value = m_decl_map.GetSpecialValue(lldb_private::ConstString(name_str.c_str()));
-
- indirect_variable = false;
- }
-
- if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void)
- {
- if (resolved_value.GetContextType() == lldb_private::Value::eContextTypeRegisterInfo)
- {
- bool bare_register = (flags & lldb_private::ClangExpressionVariable::EVBareRegister);
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (bare_register)
- indirect_variable = false;
-
- Memory::Region data_region = m_memory.Malloc(value->getType());
- data_region.m_allocation->m_origin = resolved_value;
- Memory::Region ref_region = m_memory.Malloc(value->getType());
- Memory::Region pointer_region;
-
- if (indirect_variable)
- pointer_region = m_memory.Malloc(value->getType());
-
- if (!Cache(data_region.m_allocation, value->getType()))
- return Memory::Region();
-
- if (ref_region.IsInvalid())
- return Memory::Region();
-
- if (pointer_region.IsInvalid() && indirect_variable)
- return Memory::Region();
-
- DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
-
- if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
- return Memory::Region();
-
- if (log)
- {
- log->Printf("Made an allocation for register variable %s", PrintValue(value).c_str());
- log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
- log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base);
- log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base);
- if (indirect_variable)
- log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
- }
-
- if (indirect_variable)
- {
- DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
-
- if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
- return Memory::Region();
-
- m_values[value] = pointer_region;
- return pointer_region;
- }
- else
- {
- m_values[value] = ref_region;
- return ref_region;
- }
- }
- else
- {
- Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value);
- Memory::Region ref_region = m_memory.Malloc(value->getType());
- Memory::Region pointer_region;
-
- if (indirect_variable)
- pointer_region = m_memory.Malloc(value->getType());
-
- if (ref_region.IsInvalid())
- return Memory::Region();
-
- if (pointer_region.IsInvalid() && indirect_variable)
- return Memory::Region();
-
- DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
-
- if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
- return Memory::Region();
-
- if (indirect_variable)
- {
- DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
-
- if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
- return Memory::Region();
-
- m_values[value] = pointer_region;
- }
-
- if (log)
- {
- log->Printf("Made an allocation for %s", PrintValue(value).c_str());
- log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
- log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base);
- log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base);
- if (indirect_variable)
- log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
- }
-
- if (indirect_variable)
- return pointer_region;
- else
- return ref_region;
- }
- }
+ if (log)
+ {
+ log->Printf("Made an allocation for argument %s", PrintValue(value).c_str());
+ log->Printf(" Data region : %llx", (unsigned long long)address);
+ log->Printf(" Ref region : %llx", (unsigned long long)data_address);
}
- while(0);
- // Fall back and allocate space [allocation type Alloca]
+ return true;
+ }
+
+ bool ResolveConstant (lldb::addr_t process_address, const Constant *constant)
+ {
+ APInt resolved_value;
- Type *type = value->getType();
+ if (!ResolveConstantValue(resolved_value, constant))
+ return false;
- lldb::ValueSP backing_value(new lldb_private::Value);
-
- Memory::Region data_region = m_memory.Malloc(type);
- data_region.m_allocation->m_origin.GetScalar() = (unsigned long long)data_region.m_allocation->m_data->GetBytes();
- data_region.m_allocation->m_origin.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
- data_region.m_allocation->m_origin.SetValueType(lldb_private::Value::eValueTypeHostAddress);
+ const uint64_t *raw_data = resolved_value.getRawData();
+
+ size_t constant_size = m_target_data.getTypeStoreSize(constant->getType());
- const Constant *constant = dyn_cast<Constant>(value);
+ lldb_private::Error write_error;
- do
- {
- if (!constant)
- break;
-
- if (!ResolveConstant (data_region, constant))
- return Memory::Region();
- }
- while(0);
+ m_memory_map.WriteMemory(process_address, (uint8_t*)raw_data, constant_size, write_error);
- m_values[value] = data_region;
- return data_region;
+ return write_error.Success();
}
- bool ConstructResult (lldb::ClangExpressionVariableSP &result,
- const GlobalValue *result_value,
- const lldb_private::ConstString &result_name,
- lldb_private::TypeFromParser result_type,
- Module &module)
+ lldb::addr_t Malloc (size_t size, uint8_t byte_alignment)
{
- // The result_value resolves to P, a pointer to a region R containing the result data.
- // If the result variable is a reference, the region R contains a pointer to the result R_final in the original process.
+ lldb::addr_t ret = m_stack_pointer;
- if (!result_value)
- return true; // There was no slot for a result – the expression doesn't return one.
+ ret -= size;
+ ret -= (ret % byte_alignment);
- ValueMap::iterator i = m_values.find(result_value);
-
- if (i == m_values.end())
- return false; // There was a slot for the result, but we didn't write into it.
+ if (ret < m_frame_process_address)
+ return LLDB_INVALID_ADDRESS;
- Memory::Region P = i->second;
- DataExtractorSP P_extractor = m_memory.GetExtractor(P);
+ m_stack_pointer = ret;
+ return ret;
+ }
- if (!P_extractor)
- return false;
+ lldb::addr_t MallocPointer ()
+ {
+ return Malloc(m_target_data.getPointerSize(), m_target_data.getPointerPrefAlignment());
+ }
+
+ lldb::addr_t Malloc (llvm::Type *type)
+ {
+ lldb_private::Error alloc_error;
- Type *pointer_ty = result_value->getType();
- PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
- if (!pointer_ptr_ty)
- return false;
- Type *R_ty = pointer_ptr_ty->getElementType();
-
- uint32_t offset = 0;
- lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+ return Malloc(m_target_data.getTypeAllocSize(type), m_target_data.getPrefTypeAlignment(type));
+ }
+
+ std::string PrintData (lldb::addr_t addr, llvm::Type *type)
+ {
+ size_t length = m_target_data.getTypeStoreSize(type);
- Memory::Region R = m_memory.Lookup(pointer, R_ty);
+ lldb_private::DataBufferHeap buf(length, 0);
- if (R.m_allocation->m_origin.GetValueType() != lldb_private::Value::eValueTypeHostAddress ||
- !R.m_allocation->m_data)
- return false;
+ lldb_private::Error read_error;
- lldb_private::Value base;
+ m_memory_map.ReadMemory(buf.GetBytes(), addr, length, read_error);
+
+ if (!read_error.Success())
+ return std::string("<couldn't read data>");
- bool transient = false;
- bool maybe_make_load = false;
+ lldb_private::StreamString ss;
- if (m_decl_map.ResultIsReference(result_name))
+ for (size_t i = 0; i < length; i++)
{
- PointerType *R_ptr_ty = dyn_cast<PointerType>(R_ty);
- if (!R_ptr_ty)
- return false;
- Type *R_final_ty = R_ptr_ty->getElementType();
-
- DataExtractorSP R_extractor = m_memory.GetExtractor(R);
-
- if (!R_extractor)
- return false;
-
- offset = 0;
- lldb::addr_t R_pointer = R_extractor->GetAddress(&offset);
-
- Memory::Region R_final = m_memory.Lookup(R_pointer, R_final_ty);
-
- if (R_final.m_allocation)
- {
- if (R_final.m_allocation->m_data)
- transient = true; // this is a stack allocation
-
- base = R_final.m_allocation->m_origin;
- base.GetScalar() += (R_final.m_base - R_final.m_allocation->m_virtual_address);
- }
+ if ((!(i & 0xf)) && i)
+ ss.Printf("%02hhx - ", buf.GetBytes()[i]);
else
+ ss.Printf("%02hhx ", buf.GetBytes()[i]);
+ }
+
+ return ss.GetString();
+ }
+
+ lldb::addr_t ResolveValue (const Value *value, Module &module)
+ {
+ ValueMap::iterator i = m_values.find(value);
+
+ if (i != m_values.end())
+ return i->second;
+
+ // Fall back and allocate space [allocation type Alloca]
+
+ lldb::addr_t data_address = Malloc(value->getType());
+
+ if (const Constant *constant = dyn_cast<Constant>(value))
+ {
+ if (!ResolveConstant (data_address, constant))
{
- // We got a bare pointer. We are going to treat it as a load address
- // or a file address, letting decl_map make the choice based on whether
- // or not a process exists.
-
- base.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
- base.SetValueType(lldb_private::Value::eValueTypeFileAddress);
- base.GetScalar() = (unsigned long long)R_pointer;
- maybe_make_load = true;
+ lldb_private::Error free_error;
+ m_memory_map.Free(data_address, free_error);
+ return LLDB_INVALID_ADDRESS;
}
}
- else
- {
- base.SetContext(lldb_private::Value::eContextTypeInvalid, NULL);
- base.SetValueType(lldb_private::Value::eValueTypeHostAddress);
- base.GetScalar() = (unsigned long long)R.m_allocation->m_data->GetBytes() + (R.m_base - R.m_allocation->m_virtual_address);
- }
-
- return m_decl_map.CompleteResultVariable (result, base, result_name, result_type, transient, maybe_make_load);
+
+ m_values[value] = data_address;
+ return data_address;
}
};
-bool
-IRInterpreter::maybeRunOnFunction (lldb::ClangExpressionVariableSP &result,
- const lldb_private::ConstString &result_name,
- lldb_private::TypeFromParser result_type,
- Function &llvm_function,
- Module &llvm_module,
- lldb_private::Error &err)
-{
- if (supportsFunction (llvm_function, err))
- return runOnFunction(result,
- result_name,
- result_type,
- llvm_function,
- llvm_module,
- err);
- else
- return false;
-}
-
static const char *unsupported_opcode_error = "Interpreter doesn't handle one of the expression's opcodes";
-static const char *interpreter_initialization_error = "Interpreter couldn't be initialized";
+static const char *unsupported_operand_error = "Interpreter doesn't handle one of the expression's operands";
+//static const char *interpreter_initialization_error = "Interpreter couldn't be initialized";
static const char *interpreter_internal_error = "Interpreter encountered an internal error";
static const char *bad_value_error = "Interpreter couldn't resolve a value during execution";
static const char *memory_allocation_error = "Interpreter couldn't allocate memory";
static const char *memory_write_error = "Interpreter couldn't write to memory";
static const char *memory_read_error = "Interpreter couldn't read from memory";
static const char *infinite_loop_error = "Interpreter ran for too many cycles";
-static const char *bad_result_error = "Result of expression is in bad memory";
+//static const char *bad_result_error = "Result of expression is in bad memory";
bool
-IRInterpreter::supportsFunction (Function &llvm_function,
- lldb_private::Error &err)
+IRInterpreter::CanInterpret (llvm::Module &module,
+ llvm::Function &function,
+ lldb_private::Error &error)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- for (Function::iterator bbi = llvm_function.begin(), bbe = llvm_function.end();
+ for (Function::iterator bbi = function.begin(), bbe = function.end();
bbi != bbe;
++bbi)
{
@@ -940,8 +442,8 @@ IRInterpreter::supportsFunction (Functio
{
if (log)
log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(unsupported_opcode_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
return false;
}
case Instruction::Add:
@@ -956,22 +458,22 @@ IRInterpreter::supportsFunction (Functio
if (!icmp_inst)
{
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
switch (icmp_inst->getPredicate())
{
default:
- {
- if (log)
- log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
-
- err.SetErrorToGenericError();
- err.SetErrorString(unsupported_opcode_error);
- return false;
- }
+ {
+ if (log)
+ log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str());
+
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
+ return false;
+ }
case CmpInst::ICMP_EQ:
case CmpInst::ICMP_NE:
case CmpInst::ICMP_UGT:
@@ -986,81 +488,106 @@ IRInterpreter::supportsFunction (Functio
}
}
break;
+ case Instruction::And:
+ case Instruction::AShr:
case Instruction::IntToPtr:
+ case Instruction::PtrToInt:
case Instruction::Load:
+ case Instruction::LShr:
case Instruction::Mul:
+ case Instruction::Or:
case Instruction::Ret:
case Instruction::SDiv:
+ case Instruction::SExt:
+ case Instruction::Shl:
+ case Instruction::SRem:
case Instruction::Store:
case Instruction::Sub:
case Instruction::UDiv:
+ case Instruction::URem:
+ case Instruction::Xor:
case Instruction::ZExt:
break;
}
+
+ for (int oi = 0, oe = ii->getNumOperands();
+ oi != oe;
+ ++oi)
+ {
+ Value *operand = ii->getOperand(oi);
+ Type *operand_type = operand->getType();
+
+ switch (operand_type->getTypeID())
+ {
+ default:
+ break;
+ case Type::VectorTyID:
+ {
+ if (log)
+ log->Printf("Unsupported operand type: %s", PrintType(operand_type).c_str());
+ error.SetErrorString(unsupported_operand_error);
+ return false;
+ }
+ }
+ }
}
+
}
- return true;
-}
+ return true;}
-bool
-IRInterpreter::runOnFunction (lldb::ClangExpressionVariableSP &result,
- const lldb_private::ConstString &result_name,
- lldb_private::TypeFromParser result_type,
- Function &llvm_function,
- Module &llvm_module,
- lldb_private::Error &err)
+bool
+IRInterpreter::Interpret (llvm::Module &module,
+ llvm::Function &function,
+ llvm::ArrayRef<lldb::addr_t> args,
+ lldb_private::IRMemoryMap &memory_map,
+ lldb_private::Error &error,
+ lldb::addr_t stack_frame_bottom,
+ lldb::addr_t stack_frame_top)
{
- lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- lldb_private::ClangExpressionDeclMap::TargetInfo target_info = m_decl_map.GetTargetInfo();
-
- if (!target_info.IsValid())
+ if (log)
{
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_initialization_error);
- return false;
+ std::string s;
+ raw_string_ostream oss(s);
+
+ module.print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module as passed in to IRInterpreter::Interpret: \n\"%s\"", s.c_str());
}
- lldb::addr_t alloc_min;
- lldb::addr_t alloc_max;
+ DataLayout data_layout(&module);
- switch (target_info.address_byte_size)
- {
- default:
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_initialization_error);
- return false;
- case 4:
- alloc_min = 0x00001000llu;
- alloc_max = 0x0000ffffllu;
- break;
- case 8:
- alloc_min = 0x0000000000001000llu;
- alloc_max = 0x000000000000ffffllu;
- break;
- }
+ InterpreterStackFrame frame(data_layout, memory_map, stack_frame_bottom, stack_frame_top);
- TargetData target_data(&llvm_module);
- if (target_data.getPointerSize() != target_info.address_byte_size)
+ if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS)
{
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_initialization_error);
- return false;
+ error.SetErrorString("Couldn't allocate stack frame");
}
- if (target_data.isLittleEndian() != (target_info.byte_order == lldb::eByteOrderLittle))
+
+ int arg_index = 0;
+
+ for (llvm::Function::arg_iterator ai = function.arg_begin(), ae = function.arg_end();
+ ai != ae;
+ ++ai, ++arg_index)
{
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_initialization_error);
- return false;
+ if (args.size() < arg_index)
+ {
+ error.SetErrorString ("Not enough arguments passed in to function");
+ return false;
+ }
+
+ lldb::addr_t ptr = args[arg_index];
+
+ frame.MakeArgument(ai, ptr);
}
- Memory memory(target_data, m_decl_map, alloc_min, alloc_max);
- InterpreterStackFrame frame(target_data, memory, m_decl_map);
-
uint32_t num_insts = 0;
- frame.Jump(llvm_function.begin());
+ frame.Jump(function.begin());
while (frame.m_ii != frame.m_ie && (++num_insts < 4096))
{
@@ -1071,13 +598,21 @@ IRInterpreter::runOnFunction (lldb::Clan
switch (inst->getOpcode())
{
- default:
- break;
- case Instruction::Add:
- case Instruction::Sub:
- case Instruction::Mul:
- case Instruction::SDiv:
- case Instruction::UDiv:
+ default:
+ break;
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::SDiv:
+ case Instruction::UDiv:
+ case Instruction::SRem:
+ case Instruction::URem:
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::AShr:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
{
const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
@@ -1085,9 +620,9 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns %s, but instruction is not a BinaryOperator", inst->getOpcodeName());
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
- return false;
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
}
Value *lhs = inst->getOperand(0);
@@ -1096,21 +631,21 @@ IRInterpreter::runOnFunction (lldb::Clan
lldb_private::Scalar L;
lldb_private::Scalar R;
- if (!frame.EvaluateValue(L, lhs, llvm_module))
+ if (!frame.EvaluateValue(L, lhs, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- if (!frame.EvaluateValue(R, rhs, llvm_module))
+ if (!frame.EvaluateValue(R, rhs, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
@@ -1118,26 +653,55 @@ IRInterpreter::runOnFunction (lldb::Clan
switch (inst->getOpcode())
{
- default:
- break;
- case Instruction::Add:
- result = L + R;
- break;
- case Instruction::Mul:
- result = L * R;
- break;
- case Instruction::Sub:
- result = L - R;
- break;
- case Instruction::SDiv:
- result = L / R;
- break;
- case Instruction::UDiv:
- result = L.GetRawBits64(0) / R.GetRawBits64(1);
- break;
+ default:
+ break;
+ case Instruction::Add:
+ result = L + R;
+ break;
+ case Instruction::Mul:
+ result = L * R;
+ break;
+ case Instruction::Sub:
+ result = L - R;
+ break;
+ case Instruction::SDiv:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = L / R;
+ break;
+ case Instruction::UDiv:
+ result = L.GetRawBits64(0) / R.GetRawBits64(1);
+ break;
+ case Instruction::SRem:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = L % R;
+ break;
+ case Instruction::URem:
+ result = L.GetRawBits64(0) % R.GetRawBits64(1);
+ break;
+ case Instruction::Shl:
+ result = L << R;
+ break;
+ case Instruction::AShr:
+ result = L >> R;
+ break;
+ case Instruction::LShr:
+ result = L;
+ result.ShiftRightLogical(R);
+ break;
+ case Instruction::And:
+ result = L & R;
+ break;
+ case Instruction::Or:
+ result = L | R;
+ break;
+ case Instruction::Xor:
+ result = L ^ R;
+ break;
}
-
- frame.AssignValue(inst, result, llvm_module);
+
+ frame.AssignValue(inst, result, module);
if (log)
{
@@ -1147,8 +711,8 @@ IRInterpreter::runOnFunction (lldb::Clan
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
- break;
- case Instruction::Alloca:
+ break;
+ case Instruction::Alloca:
{
const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
@@ -1156,8 +720,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1165,8 +729,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("AllocaInsts are not handled if isArrayAllocation() is true");
- err.SetErrorToGenericError();
- err.SetErrorString(unsupported_opcode_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(unsupported_opcode_error);
return false;
}
@@ -1178,36 +742,41 @@ IRInterpreter::runOnFunction (lldb::Clan
Type *T = alloca_inst->getAllocatedType();
Type *Tptr = alloca_inst->getType();
- Memory::Region R = memory.Malloc(T);
+ lldb::addr_t R = frame.Malloc(T);
- if (R.IsInvalid())
+ if (R == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("Couldn't allocate memory for an AllocaInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_allocation_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_allocation_error);
return false;
}
- Memory::Region P = memory.Malloc(Tptr);
+ lldb::addr_t P = frame.Malloc(Tptr);
- if (P.IsInvalid())
+ if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("Couldn't allocate the result pointer for an AllocaInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_allocation_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_allocation_error);
return false;
}
- DataEncoderSP P_encoder = memory.GetEncoder(P);
+ lldb_private::Error write_error;
+
+ memory_map.WritePointerToMemory(P, R, write_error);
- if (P_encoder->PutAddress(0, R.m_base) == UINT32_MAX)
+ if (!write_error.Success())
{
if (log)
log->Printf("Couldn't write the result pointer for an AllocaInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_write_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_write_error);
+ lldb_private::Error free_error;
+ memory_map.Free(P, free_error);
+ memory_map.Free(R, free_error);
return false;
}
@@ -1216,13 +785,13 @@ IRInterpreter::runOnFunction (lldb::Clan
if (log)
{
log->Printf("Interpreted an AllocaInst");
- log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
- log->Printf(" P : %s", frame.SummarizeValue(alloca_inst).c_str());
+ log->Printf(" R : 0x%" PRIx64, R);
+ log->Printf(" P : 0x%" PRIx64, P);
}
}
- break;
- case Instruction::BitCast:
- case Instruction::ZExt:
+ break;
+ case Instruction::BitCast:
+ case Instruction::ZExt:
{
const CastInst *cast_inst = dyn_cast<CastInst>(inst);
@@ -1230,8 +799,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1239,19 +808,52 @@ IRInterpreter::runOnFunction (lldb::Clan
lldb_private::Scalar S;
- if (!frame.EvaluateValue(S, source, llvm_module))
+ if (!frame.EvaluateValue(S, source, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- frame.AssignValue(inst, S, llvm_module);
+ frame.AssignValue(inst, S, module);
}
- break;
- case Instruction::Br:
+ break;
+ case Instruction::SExt:
+ {
+ const CastInst *cast_inst = dyn_cast<CastInst>(inst);
+
+ if (!cast_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *source = cast_inst->getOperand(0);
+
+ lldb_private::Scalar S;
+
+ if (!frame.EvaluateValue(S, source, module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ S.MakeSigned();
+
+ lldb_private::Scalar S_signextend(S.SLongLong());
+
+ frame.AssignValue(inst, S_signextend, module);
+ }
+ break;
+ case Instruction::Br:
{
const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
@@ -1259,8 +861,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns Br, but instruction is not a BranchInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1270,15 +872,15 @@ IRInterpreter::runOnFunction (lldb::Clan
lldb_private::Scalar C;
- if (!frame.EvaluateValue(C, condition, llvm_module))
+ if (!frame.EvaluateValue(C, condition, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
-
+
if (C.GetRawBits64(0))
frame.Jump(br_inst->getSuccessor(0));
else
@@ -1300,8 +902,8 @@ IRInterpreter::runOnFunction (lldb::Clan
}
}
}
- continue;
- case Instruction::GetElementPtr:
+ continue;
+ case Instruction::GetElementPtr:
{
const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
@@ -1309,25 +911,25 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
-
+
const Value *pointer_operand = gep_inst->getPointerOperand();
Type *pointer_type = pointer_operand->getType();
lldb_private::Scalar P;
- if (!frame.EvaluateValue(P, pointer_operand, llvm_module))
+ if (!frame.EvaluateValue(P, pointer_operand, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
-
+
typedef SmallVector <Value *, 8> IndexVector;
typedef IndexVector::iterator IndexIterator;
@@ -1346,12 +948,12 @@ IRInterpreter::runOnFunction (lldb::Clan
{
lldb_private::Scalar I;
- if (!frame.EvaluateValue(I, *ii, llvm_module))
+ if (!frame.EvaluateValue(I, *ii, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
@@ -1364,11 +966,11 @@ IRInterpreter::runOnFunction (lldb::Clan
const_indices.push_back(constant_index);
}
- uint64_t offset = target_data.getIndexedOffset(pointer_type, const_indices);
+ uint64_t offset = data_layout.getIndexedOffset(pointer_type, const_indices);
lldb_private::Scalar Poffset = P + offset;
- frame.AssignValue(inst, Poffset, llvm_module);
+ frame.AssignValue(inst, Poffset, module);
if (log)
{
@@ -1377,8 +979,8 @@ IRInterpreter::runOnFunction (lldb::Clan
log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str());
}
}
- break;
- case Instruction::ICmp:
+ break;
+ case Instruction::ICmp:
{
const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
@@ -1386,8 +988,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1399,63 +1001,71 @@ IRInterpreter::runOnFunction (lldb::Clan
lldb_private::Scalar L;
lldb_private::Scalar R;
- if (!frame.EvaluateValue(L, lhs, llvm_module))
+ if (!frame.EvaluateValue(L, lhs, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- if (!frame.EvaluateValue(R, rhs, llvm_module))
+ if (!frame.EvaluateValue(R, rhs, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
lldb_private::Scalar result;
-
+
switch (predicate)
{
- default:
- return false;
- case CmpInst::ICMP_EQ:
- result = (L == R);
- break;
- case CmpInst::ICMP_NE:
- result = (L != R);
- break;
- case CmpInst::ICMP_UGT:
- result = (L.GetRawBits64(0) > R.GetRawBits64(0));
- break;
- case CmpInst::ICMP_UGE:
- result = (L.GetRawBits64(0) >= R.GetRawBits64(0));
- break;
- case CmpInst::ICMP_ULT:
- result = (L.GetRawBits64(0) < R.GetRawBits64(0));
- break;
- case CmpInst::ICMP_ULE:
- result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
- break;
- case CmpInst::ICMP_SGT:
- result = (L > R);
- break;
- case CmpInst::ICMP_SGE:
- result = (L >= R);
- break;
- case CmpInst::ICMP_SLT:
- result = (L < R);
- break;
- case CmpInst::ICMP_SLE:
- result = (L <= R);
- break;
+ default:
+ return false;
+ case CmpInst::ICMP_EQ:
+ result = (L == R);
+ break;
+ case CmpInst::ICMP_NE:
+ result = (L != R);
+ break;
+ case CmpInst::ICMP_UGT:
+ result = (L.GetRawBits64(0) > R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_UGE:
+ result = (L.GetRawBits64(0) >= R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_ULT:
+ result = (L.GetRawBits64(0) < R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_ULE:
+ result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_SGT:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L > R);
+ break;
+ case CmpInst::ICMP_SGE:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L >= R);
+ break;
+ case CmpInst::ICMP_SLT:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L < R);
+ break;
+ case CmpInst::ICMP_SLE:
+ L.MakeSigned();
+ R.MakeSigned();
+ result = (L <= R);
+ break;
}
- frame.AssignValue(inst, result, llvm_module);
+ frame.AssignValue(inst, result, module);
if (log)
{
@@ -1465,8 +1075,8 @@ IRInterpreter::runOnFunction (lldb::Clan
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
- break;
- case Instruction::IntToPtr:
+ break;
+ case Instruction::IntToPtr:
{
const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
@@ -1474,8 +1084,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1483,26 +1093,62 @@ IRInterpreter::runOnFunction (lldb::Clan
lldb_private::Scalar I;
- if (!frame.EvaluateValue(I, src_operand, llvm_module))
+ if (!frame.EvaluateValue(I, src_operand, module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- frame.AssignValue(inst, I, llvm_module);
+ frame.AssignValue(inst, I, module);
if (log)
{
log->Printf("Interpreted an IntToPtr");
log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
- log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
- break;
- case Instruction::Load:
+ break;
+ case Instruction::PtrToInt:
+ {
+ const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
+
+ if (!ptr_to_int_inst)
+ {
+ if (log)
+ log->Printf("getOpcode() returns PtrToInt, but instruction is not an PtrToIntInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
+ return false;
+ }
+
+ Value *src_operand = ptr_to_int_inst->getOperand(0);
+
+ lldb_private::Scalar I;
+
+ if (!frame.EvaluateValue(I, src_operand, module))
+ {
+ if (log)
+ log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
+ return false;
+ }
+
+ frame.AssignValue(inst, I, module);
+
+ if (log)
+ {
+ log->Printf("Interpreted a PtrToInt");
+ log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
+ log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
+ }
+ }
+ break;
+ case Instruction::Load:
{
const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
@@ -1510,8 +1156,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns Load, but instruction is not a LoadInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1520,7 +1166,7 @@ IRInterpreter::runOnFunction (lldb::Clan
// Resolve the region P containing a pointer
// Dereference P to get the region R that the data should be loaded from
// Transfer a unit of type type(D) from R to D
-
+
const Value *pointer_operand = load_inst->getPointerOperand();
Type *pointer_ty = pointer_operand->getType();
@@ -1529,95 +1175,85 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getPointerOperand()->getType() is not a PointerType");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
Type *target_ty = pointer_ptr_ty->getElementType();
- Memory::Region D = frame.ResolveValue(load_inst, llvm_module);
- Memory::Region P = frame.ResolveValue(pointer_operand, llvm_module);
+ lldb::addr_t D = frame.ResolveValue(load_inst, module);
+ lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
- if (D.IsInvalid())
+ if (D == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("LoadInst's value doesn't resolve to anything");
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- if (P.IsInvalid())
+ if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("LoadInst's pointer doesn't resolve to anything");
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- DataExtractorSP P_extractor(memory.GetExtractor(P));
- DataEncoderSP D_encoder(memory.GetEncoder(D));
-
- uint32_t offset = 0;
- lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+ lldb::addr_t R;
+ lldb_private::Error read_error;
+ memory_map.ReadPointerFromMemory(&R, P, read_error);
- Memory::Region R = memory.Lookup(pointer, target_ty);
+ if (!read_error.Success())
+ {
+ if (log)
+ log->Printf("Couldn't read the address to be loaded for a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
- if (R.IsValid())
+ size_t target_size = data_layout.getTypeStoreSize(target_ty);
+ lldb_private::DataBufferHeap buffer(target_size, 0);
+
+ read_error.Clear();
+ memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error);
+ if (!read_error.Success())
{
- if (!memory.Read(D_encoder->GetDataStart(), R.m_base, target_data.getTypeStoreSize(target_ty)))
- {
- if (log)
- log->Printf("Couldn't read from a region on behalf of a LoadInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_read_error);
- return false;
- }
+ if (log)
+ log->Printf("Couldn't read from a region on behalf of a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
}
- else
+
+ lldb_private::Error write_error;
+ memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error);
+ if (!write_error.Success())
{
- if (!memory.ReadFromRawPtr(D_encoder->GetDataStart(), pointer, target_data.getTypeStoreSize(target_ty)))
- {
- if (log)
- log->Printf("Couldn't read from a raw pointer on behalf of a LoadInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_read_error);
- return false;
- }
+ if (log)
+ log->Printf("Couldn't write to a region on behalf of a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
}
if (log)
{
log->Printf("Interpreted a LoadInst");
- log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
- if (R.IsValid())
- log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
- else
- log->Printf(" R : raw pointer 0x%llx", (unsigned long long)pointer);
- log->Printf(" D : %s", frame.SummarizeValue(load_inst).c_str());
+ log->Printf(" P : 0x%" PRIx64, P);
+ log->Printf(" R : 0x%" PRIx64, R);
+ log->Printf(" D : 0x%" PRIx64, D);
}
}
- break;
- case Instruction::Ret:
+ break;
+ case Instruction::Ret:
{
- if (result_name.IsEmpty())
- return true;
-
- GlobalValue *result_value = llvm_module.getNamedValue(result_name.GetCString());
-
- if (!frame.ConstructResult(result, result_value, result_name, result_type, llvm_module))
- {
- if (log)
- log->Printf("Couldn't construct the expression's result");
- err.SetErrorToGenericError();
- err.SetErrorString(bad_result_error);
- return false;
- }
-
return true;
}
- case Instruction::Store:
+ case Instruction::Store:
{
const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
@@ -1625,8 +1261,8 @@ IRInterpreter::runOnFunction (lldb::Clan
{
if (log)
log->Printf("getOpcode() returns Store, but instruction is not a StoreInst");
- err.SetErrorToGenericError();
- err.SetErrorString(interpreter_internal_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(interpreter_internal_error);
return false;
}
@@ -1645,71 +1281,74 @@ IRInterpreter::runOnFunction (lldb::Clan
return false;
Type *target_ty = pointer_ptr_ty->getElementType();
- Memory::Region D = frame.ResolveValue(value_operand, llvm_module);
- Memory::Region P = frame.ResolveValue(pointer_operand, llvm_module);
+ lldb::addr_t D = frame.ResolveValue(value_operand, module);
+ lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
- if (D.IsInvalid())
+ if (D == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("StoreInst's value doesn't resolve to anything");
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- if (P.IsInvalid())
+ if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("StoreInst's pointer doesn't resolve to anything");
- err.SetErrorToGenericError();
- err.SetErrorString(bad_value_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(bad_value_error);
return false;
}
- DataExtractorSP P_extractor(memory.GetExtractor(P));
- DataExtractorSP D_extractor(memory.GetExtractor(D));
-
- if (!P_extractor || !D_extractor)
- return false;
+ lldb::addr_t R;
+ lldb_private::Error read_error;
+ memory_map.ReadPointerFromMemory(&R, P, read_error);
- uint32_t offset = 0;
- lldb::addr_t pointer = P_extractor->GetAddress(&offset);
+ if (!read_error.Success())
+ {
+ if (log)
+ log->Printf("Couldn't read the address to be loaded for a LoadInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
+ }
- Memory::Region R = memory.Lookup(pointer, target_ty);
+ size_t target_size = data_layout.getTypeStoreSize(target_ty);
+ lldb_private::DataBufferHeap buffer(target_size, 0);
- if (R.IsValid())
+ read_error.Clear();
+ memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error);
+ if (!read_error.Success())
{
- if (!memory.Write(R.m_base, D_extractor->GetDataStart(), target_data.getTypeStoreSize(target_ty)))
- {
- if (log)
- log->Printf("Couldn't write to a region on behalf of a LoadInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_write_error);
- return false;
- }
+ if (log)
+ log->Printf("Couldn't read from a region on behalf of a StoreInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_read_error);
+ return false;
}
- else
+
+ lldb_private::Error write_error;
+ memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error);
+ if (!write_error.Success())
{
- if (!memory.WriteToRawPtr(pointer, D_extractor->GetDataStart(), target_data.getTypeStoreSize(target_ty)))
- {
- if (log)
- log->Printf("Couldn't write to a raw pointer on behalf of a LoadInst");
- err.SetErrorToGenericError();
- err.SetErrorString(memory_write_error);
- return false;
- }
+ if (log)
+ log->Printf("Couldn't write to a region on behalf of a StoreInst");
+ error.SetErrorToGenericError();
+ error.SetErrorString(memory_write_error);
+ return false;
}
-
if (log)
{
log->Printf("Interpreted a StoreInst");
- log->Printf(" D : %s", frame.SummarizeValue(value_operand).c_str());
- log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
- log->Printf(" R : %s", memory.SummarizeRegion(R).c_str());
+ log->Printf(" D : 0x%" PRIx64, D);
+ log->Printf(" P : 0x%" PRIx64, P);
+ log->Printf(" R : 0x%" PRIx64, R);
}
}
- break;
+ break;
}
++frame.m_ii;
@@ -1717,10 +1356,10 @@ IRInterpreter::runOnFunction (lldb::Clan
if (num_insts >= 4096)
{
- err.SetErrorToGenericError();
- err.SetErrorString(infinite_loop_error);
+ error.SetErrorToGenericError();
+ error.SetErrorString(infinite_loop_error);
return false;
}
-
- return false;
+
+ return false;
}
Copied: lldb/branches/lldb-platform-work/source/Expression/IRMemoryMap.cpp (from r182522, lldb/trunk/source/Expression/IRMemoryMap.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/IRMemoryMap.cpp?p2=lldb/branches/lldb-platform-work/source/Expression/IRMemoryMap.cpp&p1=lldb/trunk/source/Expression/IRMemoryMap.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRMemoryMap.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/IRMemoryMap.cpp Thu Jun 6 19:06:43 2013
@@ -38,7 +38,10 @@ IRMemoryMap::~IRMemoryMap ()
while ((iter = m_allocations.begin()) != m_allocations.end())
{
err.Clear();
- Free(iter->first, err);
+ if (iter->second.m_leak)
+ m_allocations.erase(iter);
+ else
+ Free(iter->first, err);
}
}
}
@@ -357,7 +360,7 @@ IRMemoryMap::Malloc (size_t size, uint8_
break;
}
- log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
+ log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
(uint64_t)allocation_size,
(uint64_t)alignment,
(uint64_t)permissions,
@@ -369,6 +372,25 @@ IRMemoryMap::Malloc (size_t size, uint8_
}
void
+IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
+{
+ error.Clear();
+
+ AllocationMap::iterator iter = m_allocations.find(process_address);
+
+ if (iter == m_allocations.end())
+ {
+ error.SetErrorToGenericError();
+ error.SetErrorString("Couldn't leak: allocation doesn't exist");
+ return;
+ }
+
+ Allocation &allocation = iter->second;
+
+ allocation.m_leak = true;
+}
+
+void
IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
{
error.Clear();
@@ -411,7 +433,7 @@ IRMemoryMap::Free (lldb::addr_t process_
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
+ log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
(uint64_t)process_address,
iter->second.m_process_start,
iter->second.m_process_start + iter->second.m_size);
@@ -492,7 +514,7 @@ IRMemoryMap::WriteMemory (lldb::addr_t p
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
+ log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
(uint64_t)process_address,
(uint64_t)bytes,
(uint64_t)size,
@@ -625,7 +647,7 @@ IRMemoryMap::ReadMemory (uint8_t *bytes,
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
+ log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
(uint64_t)process_address,
(uint64_t)bytes,
(uint64_t)size,
@@ -655,7 +677,7 @@ IRMemoryMap::ReadScalarFromMemory (Scala
{
default:
error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
+ error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
return;
case 1: scalar = extractor.GetU8(&offset); break;
case 2: scalar = extractor.GetU16(&offset); break;
@@ -699,7 +721,7 @@ IRMemoryMap::GetMemoryData (DataExtracto
if (iter == m_allocations.end())
{
error.SetErrorToGenericError();
- error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
+ error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
return;
}
Copied: lldb/branches/lldb-platform-work/source/Expression/Materializer.cpp (from r182522, lldb/trunk/source/Expression/Materializer.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/Materializer.cpp?p2=lldb/branches/lldb-platform-work/source/Expression/Materializer.cpp&p1=lldb/trunk/source/Expression/Materializer.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Expression/Materializer.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/Materializer.cpp Thu Jun 6 19:06:43 2013
@@ -109,7 +109,11 @@ public:
// Clear the flag if the variable will never be deallocated.
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+ {
+ Error leak_error;
+ map.Leak(mem, leak_error);
m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
+ }
// Write the contents of the variable to the area.
@@ -148,7 +152,7 @@ public:
if (log)
{
- log->Printf("EntityPersistentVariable::Materialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
+ log->Printf("EntityPersistentVariable::Materialize [process_address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
(uint64_t)process_address,
m_persistent_variable_sp->GetName().AsCString(),
m_persistent_variable_sp->m_flags);
@@ -192,7 +196,7 @@ public:
if (log)
{
- log->Printf("EntityPersistentVariable::Dematerialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
+ log->Printf("EntityPersistentVariable::Dematerialize [process_address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
(uint64_t)process_address,
m_persistent_variable_sp->GetName().AsCString(),
m_persistent_variable_sp->m_flags);
@@ -314,7 +318,7 @@ public:
Error err;
- dump_stream.Printf("0x%llx: EntityPersistentVariable (%s)\n", (unsigned long long)process_address + m_offset, m_persistent_variable_sp->GetName().AsCString());
+ dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", process_address + m_offset, m_persistent_variable_sp->GetName().AsCString());
{
dump_stream.Printf("Pointer:\n");
@@ -411,7 +415,7 @@ public:
if (log)
{
- log->Printf("EntityVariable::Materialize [process_address = 0x%llx, m_variable_sp = %s]",
+ log->Printf("EntityVariable::Materialize [process_address = 0x%" PRIx64 ", m_variable_sp = %s]",
(uint64_t)process_address,
m_variable_sp->GetName().AsCString());
}
@@ -532,7 +536,7 @@ public:
if (log)
{
- log->Printf("EntityVariable::Dematerialize [process_address = 0x%llx, m_variable_sp = %s]",
+ log->Printf("EntityVariable::Dematerialize [process_address = 0x%" PRIx64 ", m_variable_sp = %s]",
(uint64_t)process_address,
m_variable_sp->GetName().AsCString());
}
@@ -593,7 +597,7 @@ public:
{
StreamString dump_stream;
- dump_stream.Printf("0x%llx: EntityVariable\n", (unsigned long long)process_address + m_offset);
+ dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", process_address + m_offset);
Error err;
@@ -850,7 +854,7 @@ public:
{
StreamString dump_stream;
- dump_stream.Printf("0x%llx: EntityResultVariable\n", (unsigned long long)process_address + m_offset);
+ dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", process_address + m_offset);
Error err;
@@ -967,7 +971,7 @@ public:
if (log)
{
- log->Printf("EntitySymbol::Materialize [process_address = 0x%llx, m_symbol = %s]",
+ log->Printf("EntitySymbol::Materialize [process_address = 0x%" PRIx64 ", m_symbol = %s]",
(uint64_t)process_address,
m_symbol.GetName().AsCString());
}
@@ -1010,7 +1014,7 @@ public:
if (log)
{
- log->Printf("EntitySymbol::Dematerialize [process_address = 0x%llx, m_symbol = %s]",
+ log->Printf("EntitySymbol::Dematerialize [process_address = 0x%" PRIx64 ", m_symbol = %s]",
(uint64_t)process_address,
m_symbol.GetName().AsCString());
}
@@ -1024,7 +1028,7 @@ public:
Error err;
- dump_stream.Printf("0x%llx: EntitySymbol (%s)\n", (unsigned long long)process_address + m_offset, m_symbol.GetName().AsCString());
+ dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", process_address + m_offset, m_symbol.GetName().AsCString());
{
dump_stream.Printf("Pointer:\n");
@@ -1085,7 +1089,7 @@ public:
if (log)
{
- log->Printf("EntityRegister::Materialize [process_address = 0x%llx, m_register_info = %s]",
+ log->Printf("EntityRegister::Materialize [process_address = 0x%" PRIx64 ", m_register_info = %s]",
(uint64_t)process_address,
m_register_info.name);
}
@@ -1138,7 +1142,7 @@ public:
if (log)
{
- log->Printf("EntityRegister::Dematerialize [process_address = 0x%llx, m_register_info = %s]",
+ log->Printf("EntityRegister::Dematerialize [process_address = 0x%" PRIx64 ", m_register_info = %s]",
(uint64_t)process_address,
m_register_info.name);
}
@@ -1178,7 +1182,7 @@ public:
Error err;
- dump_stream.Printf("0x%llx: EntityRegister (%s)\n", (unsigned long long)process_address + m_offset, m_register_info.name);
+ dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", process_address + m_offset, m_register_info.name);
{
dump_stream.Printf("Value:\n");
@@ -1271,7 +1275,7 @@ Materializer::Materialize (lldb::StackFr
if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%llx) materialized:", frame_sp.get(), process_address);
+ log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
for (EntityUP &entity_up : m_entities)
entity_up->DumpToLog(map, process_address, log);
}
@@ -1303,7 +1307,7 @@ Materializer::Dematerializer::Dematerial
{
if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
{
- log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%llx) about to dematerialize:", frame_sp.get(), m_process_address);
+ log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
for (EntityUP &entity_up : m_materializer->m_entities)
entity_up->DumpToLog(*m_map, m_process_address, log);
}
Removed: lldb/branches/lldb-platform-work/source/Expression/ProcessDataAllocator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/ProcessDataAllocator.cpp?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Expression/ProcessDataAllocator.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/ProcessDataAllocator.cpp (removed)
@@ -1,43 +0,0 @@
-//===-- ProcessDataAllocator.cpp --------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Expression/ProcessDataAllocator.h"
-
-using namespace lldb_private;
-
-void
-ProcessDataAllocator::Dump(Stream &stream)
-{
- size_t data_size = m_stream_string.GetSize();
-
- if (!m_allocation)
- return;
-
- lldb::DataBufferSP data(new DataBufferHeap(data_size, 0));
-
- Error error;
- if (m_process.ReadMemory (m_allocation, data->GetBytes(), data_size, error) != data_size)
- return;
-
- DataExtractor extractor(data, m_process.GetByteOrder(), m_process.GetAddressByteSize());
-
- extractor.Dump(&stream, // stream
- 0, // offset
- lldb::eFormatBytesWithASCII, // format
- 1, // byte size of individual entries
- data_size, // number of entries
- 16, // entries per line
- m_allocation, // address to print
- 0, // bit size (bitfields only; 0 means ignore)
- 0); // bit alignment (bitfields only; 0 means ignore)
-
- stream.PutChar('\n');
-}
Removed: lldb/branches/lldb-platform-work/source/Expression/RecordingMemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Expression/RecordingMemoryManager.cpp?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Expression/RecordingMemoryManager.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Expression/RecordingMemoryManager.cpp (removed)
@@ -1,340 +0,0 @@
-//===-- RecordingMemoryManager.cpp ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-// Project includes
-#include "lldb/Expression/RecordingMemoryManager.h"
-
-using namespace lldb_private;
-
-RecordingMemoryManager::RecordingMemoryManager () :
- llvm::JITMemoryManager(),
- m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
- m_log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
-{
-}
-
-RecordingMemoryManager::~RecordingMemoryManager ()
-{
-}
-
-void
-RecordingMemoryManager::setMemoryWritable ()
-{
- m_default_mm_ap->setMemoryWritable();
-}
-
-void
-RecordingMemoryManager::setMemoryExecutable ()
-{
- m_default_mm_ap->setMemoryExecutable();
-}
-
-
-uint8_t *
-RecordingMemoryManager::startFunctionBody(const llvm::Function *F,
- uintptr_t &ActualSize)
-{
- return m_default_mm_ap->startFunctionBody(F, ActualSize);
-}
-
-uint8_t *
-RecordingMemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSize,
- unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
-
- Allocation allocation;
- allocation.m_size = StubSize;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
- F, StubSize, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-void
-RecordingMemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart,
- uint8_t *FunctionEnd)
-{
- m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
-}
-
-uint8_t *
-RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateSpace(Size=%llu, Alignment=%u) = %p",
- (uint64_t)Size, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID)
-{
- uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
- allocation.m_executable = true;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateCodeSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID)
-{
- uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
- allocation.m_section_id = SectionID;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%llx, Alignment=%u, SectionID=%u) = %p",
- (uint64_t)Size, Alignment, SectionID, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-uint8_t *
-RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
-{
- uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
-
- Allocation allocation;
- allocation.m_size = Size;
- allocation.m_alignment = Alignment;
- allocation.m_local_start = (uintptr_t)return_value;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::allocateGlobal(Size=0x%llx, Alignment=%u) = %p",
- (uint64_t)Size, Alignment, return_value);
- allocation.dump(m_log);
- }
-
- m_allocations.push_back(allocation);
-
- return return_value;
-}
-
-void
-RecordingMemoryManager::deallocateFunctionBody(void *Body)
-{
- m_default_mm_ap->deallocateFunctionBody(Body);
-}
-
-uint8_t*
-RecordingMemoryManager::startExceptionTable(const llvm::Function* F,
- uintptr_t &ActualSize)
-{
- return m_default_mm_ap->startExceptionTable(F, ActualSize);
-}
-
-void
-RecordingMemoryManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart,
- uint8_t *TableEnd, uint8_t* FrameRegister)
-{
- m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
-}
-
-void
-RecordingMemoryManager::deallocateExceptionTable(void *ET)
-{
- m_default_mm_ap->deallocateExceptionTable (ET);
-}
-
-lldb::addr_t
-RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (local_address >= ai->m_local_start &&
- local_address < ai->m_local_start + ai->m_size)
- return ai->m_remote_start + (local_address - ai->m_local_start);
- }
-
- return LLDB_INVALID_ADDRESS;
-}
-
-RecordingMemoryManager::AddrRange
-RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (local_address >= ai->m_local_start &&
- local_address < ai->m_local_start + ai->m_size)
- return AddrRange(ai->m_remote_start, ai->m_size);
- }
-
- return AddrRange (0, 0);
-}
-
-bool
-RecordingMemoryManager::CommitAllocations (Process &process)
-{
- bool ret = true;
-
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (ai->m_allocated)
- continue;
-
- lldb_private::Error err;
-
- size_t allocation_size = (ai->m_size ? ai->m_size : 1) + ai->m_alignment - 1;
-
- if (allocation_size == 0)
- allocation_size = 1;
-
- ai->m_remote_allocation = process.AllocateMemory(
- allocation_size,
- ai->m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
- : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
- err);
-
- uint64_t mask = ai->m_alignment - 1;
-
- ai->m_remote_start = (ai->m_remote_allocation + mask) & (~mask);
-
- if (!err.Success())
- {
- ret = false;
- break;
- }
-
- ai->m_allocated = true;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation");
- ai->dump(m_log);
- }
- }
-
- if (!ret)
- {
- for (AllocationList::iterator ai = m_allocations.end(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (ai->m_allocated)
- process.DeallocateMemory(ai->m_remote_start);
- }
- }
-
- return ret;
-}
-
-void
-RecordingMemoryManager::ReportAllocations (llvm::ExecutionEngine &engine)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (!ai->m_allocated)
- continue;
-
- engine.mapSectionAddress((void*)ai->m_local_start, ai->m_remote_start);
- }
-}
-
-bool
-RecordingMemoryManager::WriteData (Process &process)
-{
- for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end();
- ai != ae;
- ++ai)
- {
- if (!ai->m_allocated)
- return false;
-
- lldb_private::Error err;
-
- if (process.WriteMemory(ai->m_remote_start,
- (void*)ai->m_local_start,
- ai->m_size,
- err) != ai->m_size ||
- !err.Success())
- return false;
-
- if (m_log)
- {
- m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation");
- ai->dump(m_log);
- }
- }
-
- return true;
-}
-
-void
-RecordingMemoryManager::Allocation::dump (lldb::LogSP log)
-{
- if (!log)
- return;
-
- log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
- (unsigned long long)m_local_start,
- (unsigned long long)m_size,
- (unsigned long long)m_remote_start,
- (unsigned)m_alignment,
- (unsigned)m_section_id);
-}
Modified: lldb/branches/lldb-platform-work/source/Host/common/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/File.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/File.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/File.cpp Thu Jun 6 19:06:43 2013
@@ -89,9 +89,7 @@ File::File (const FileSpec& filespec,
{
if (filespec)
{
- std::string path;
- filespec.GetPath(path);
- Open (path.c_str(), options, permissions);
+ Open (filespec.GetPath().c_str(), options, permissions);
}
}
@@ -263,6 +261,53 @@ File::Open (const char *path, uint32_t o
return error;
}
+uint32_t
+File::GetPermissions (const char *path, Error &error)
+{
+ if (path && path[0])
+ {
+ struct stat file_stats;
+ if (::stat (path, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ if (path)
+ error.SetErrorString ("invalid path");
+ else
+ error.SetErrorString ("empty path");
+ }
+ return 0;
+}
+
+uint32_t
+File::GetPermissions(Error &error) const
+{
+ int fd = GetDescriptor();
+ if (fd != kInvalidDescriptor)
+ {
+ struct stat file_stats;
+ if (::fstat (fd, &file_stats) == -1)
+ error.SetErrorToErrno();
+ else
+ {
+ error.Clear();
+ return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ }
+ }
+ else
+ {
+ error.SetErrorString ("invalid file descriptor");
+ }
+ return 0;
+}
+
+
Error
File::Close ()
{
@@ -334,58 +379,109 @@ File::GetFileSpec (FileSpec &file_spec)
return error;
}
-Error
-File::SeekFromStart (off_t& offset)
+off_t
+File::SeekFromStart (off_t offset, Error *error_ptr)
{
- Error error;
+ off_t result = 0;
if (DescriptorIsValid())
{
- offset = ::lseek (m_descriptor, offset, SEEK_SET);
+ result = ::lseek (m_descriptor, offset, SEEK_SET);
- if (offset == -1)
- error.SetErrorToErrno();
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- else
+ else if (StreamIsValid ())
{
- error.SetErrorString("invalid file handle");
+ result = ::fseek(m_stream, offset, SEEK_SET);
+
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- return error;
+ else if (error_ptr)
+ {
+ error_ptr->SetErrorString("invalid file handle");
+ }
+ return result;
}
-Error
-File::SeekFromCurrent (off_t& offset)
+off_t
+File::SeekFromCurrent (off_t offset, Error *error_ptr)
{
- Error error;
+ off_t result = -1;
if (DescriptorIsValid())
{
- offset = ::lseek (m_descriptor, offset, SEEK_CUR);
+ result = ::lseek (m_descriptor, offset, SEEK_CUR);
- if (offset == -1)
- error.SetErrorToErrno();
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- else
+ else if (StreamIsValid ())
{
- error.SetErrorString("invalid file handle");
+ result = ::fseek(m_stream, offset, SEEK_CUR);
+
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- return error;
+ else if (error_ptr)
+ {
+ error_ptr->SetErrorString("invalid file handle");
+ }
+ return result;
}
-Error
-File::SeekFromEnd (off_t& offset)
+off_t
+File::SeekFromEnd (off_t offset, Error *error_ptr)
{
- Error error;
+ off_t result = -1;
if (DescriptorIsValid())
{
- offset = ::lseek (m_descriptor, offset, SEEK_CUR);
+ result = ::lseek (m_descriptor, offset, SEEK_END);
- if (offset == -1)
- error.SetErrorToErrno();
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- else
+ else if (StreamIsValid ())
{
- error.SetErrorString("invalid file handle");
+ result = ::fseek(m_stream, offset, SEEK_END);
+
+ if (error_ptr)
+ {
+ if (result == -1)
+ error_ptr->SetErrorToErrno();
+ else
+ error_ptr->Clear();
+ }
}
- return error;
+ else if (error_ptr)
+ {
+ error_ptr->SetErrorString("invalid file handle");
+ }
+ return result;
}
Error
@@ -554,7 +650,7 @@ File::Read (void *buf, size_t &num_bytes
}
Error
-File::Read (size_t &num_bytes, off_t &offset, DataBufferSP &data_buffer_sp)
+File::Read (size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp)
{
Error error;
@@ -572,8 +668,8 @@ File::Read (size_t &num_bytes, off_t &of
if (num_bytes > bytes_left)
num_bytes = bytes_left;
- std::auto_ptr<DataBufferHeap> data_heap_ap;
- data_heap_ap.reset(new DataBufferHeap(num_bytes, '\0'));
+ std::unique_ptr<DataBufferHeap> data_heap_ap;
+ data_heap_ap.reset(new DataBufferHeap(num_bytes + (null_terminate ? 1 : 0), '\0'));
if (data_heap_ap.get())
{
@@ -641,12 +737,12 @@ File::Write (const void *buf, size_t &nu
//------------------------------------------------------------------
// Print some formatted output to the stream.
//------------------------------------------------------------------
-int
+size_t
File::Printf (const char *format, ...)
{
va_list args;
va_start (args, format);
- int result = PrintfVarArg (format, args);
+ size_t result = PrintfVarArg (format, args);
va_end (args);
return result;
}
@@ -654,10 +750,10 @@ File::Printf (const char *format, ...)
//------------------------------------------------------------------
// Print some formatted output to the stream.
//------------------------------------------------------------------
-int
+size_t
File::PrintfVarArg (const char *format, va_list args)
{
- int result = 0;
+ size_t result = 0;
if (DescriptorIsValid())
{
char *s = NULL;
@@ -679,3 +775,51 @@ File::PrintfVarArg (const char *format,
}
return result;
}
+
+mode_t
+File::ConvertOpenOptionsForPOSIXOpen (uint32_t open_options)
+{
+ mode_t mode = 0;
+ if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite)
+ mode |= O_RDWR;
+ else if (open_options & eOpenOptionWrite)
+ mode |= O_WRONLY;
+
+ if (open_options & eOpenOptionAppend)
+ mode |= O_APPEND;
+
+ if (open_options & eOpenOptionTruncate)
+ mode |= O_TRUNC;
+
+ if (open_options & eOpenOptionNonBlocking)
+ mode |= O_NONBLOCK;
+
+ if (open_options & eOpenOptionCanCreateNewOnly)
+ mode |= O_CREAT | O_EXCL;
+ else if (open_options & eOpenOptionCanCreate)
+ mode |= O_CREAT;
+
+ return mode;
+}
+
+#define O_RDONLY 0x0000 /* open for reading only */
+#define O_WRONLY 0x0001 /* open for writing only */
+#define O_RDWR 0x0002 /* open for reading and writing */
+#define O_ACCMODE 0x0003 /* mask for above modes */
+#define O_NONBLOCK 0x0004 /* no delay */
+#define O_APPEND 0x0008 /* set append mode */
+#define O_SYNC 0x0080 /* synch I/O file integrity */
+#define O_SHLOCK 0x0010 /* open with shared file lock */
+#define O_EXLOCK 0x0020 /* open with exclusive file lock */
+#define O_ASYNC 0x0040 /* signal pgrp when data ready */
+#define O_FSYNC O_SYNC /* source compatibility: do not use */
+#define O_NOFOLLOW 0x0100 /* don't follow symlinks */
+#define O_CREAT 0x0200 /* create if nonexistant */
+#define O_TRUNC 0x0400 /* truncate to zero length */
+#define O_EXCL 0x0800 /* error if already exists */
+#define O_EVTONLY 0x8000 /* descriptor requested for event notifications only */
+#define O_NOCTTY 0x20000 /* don't assign controlling terminal */
+#define O_DIRECTORY 0x100000
+#define O_SYMLINK 0x200000 /* allow open of a symlink */
+#define O_DSYNC 0x400000 /* synch I/O data integrity */
+#define O_CLOEXEC 0x1000000 /* implicitly set FD_CLOEXEC */
Modified: lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/FileSpec.cpp Thu Jun 6 19:06:43 2013
@@ -29,12 +29,13 @@
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataBufferMemoryMap.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/CleanUp.h"
using namespace lldb;
using namespace lldb_private;
-using namespace std;
static bool
GetFileStats (const FileSpec *file_spec, struct stat *stats_ptr)
@@ -109,7 +110,7 @@ FileSpec::ResolveUsername (const char *s
}
else
{
- int user_name_len = first_slash - src_path - 1;
+ size_t user_name_len = first_slash - src_path - 1;
::memcpy (user_home, src_path + 1, user_name_len);
user_home[user_name_len] = '\0';
user_name = user_home;
@@ -419,7 +420,7 @@ FileSpec::operator== (const FileSpec& rh
// rhs's path wasn't resolved but now it is. Check if the resolved
// directory is the same as rhs's unresolved directory, and if so,
// we can mark this object as resolved to avoid more future resolves
- rhs.m_is_resolved = (m_directory == resolved_rhs.m_directory);
+ rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory);
}
else
return false;
@@ -523,16 +524,14 @@ FileSpec::Equal (const FileSpec& a, cons
void
FileSpec::Dump(Stream *s) const
{
- if (m_filename)
- m_directory.Dump(s, ""); // Provide a default for m_directory when we dump it in case it is invalid
-
- if (m_directory)
+ static ConstString g_slash_only ("/");
+ if (s)
{
- // If dirname was valid, then we need to print a slash between
- // the directory and the filename
- s->PutChar('/');
+ m_directory.Dump(s);
+ if (m_directory && m_directory != g_slash_only)
+ s->PutChar('/');
+ m_filename.Dump(s);
}
- m_filename.Dump(s);
}
//------------------------------------------------------------------
@@ -676,34 +675,6 @@ FileSpec::GetFilename() const
return m_filename;
}
-size_t
-FileSpec::GetPath (std::string& path) const
-{
- const char *dirname = m_directory.GetCString();
- const char *filename = m_filename.GetCString();
-
- uint32_t max_len = (dirname ? strlen(dirname) : 0) + (filename ? strlen(filename) : 0) + 2;
-
- path.resize(max_len);
-
- if (dirname)
- {
- if (filename)
- return ::snprintf (&path[0], max_len, "%s/%s", dirname, filename);
- else
- return ::snprintf (&path[0], max_len, "%s", dirname);
- }
- else if (filename)
- {
- return ::snprintf (&path[0], max_len, "%s", filename);
- }
- else
- {
- path.clear();
- return 0;
- }
-}
-
//------------------------------------------------------------------
// Extract the directory and path into a fixed buffer. This is
// needed as the directory and path are stored in separate string
@@ -733,18 +704,35 @@ FileSpec::GetPath(char *path, size_t pat
return 0;
}
+std::string
+FileSpec::GetPath (void) const
+{
+ static ConstString g_slash_only ("/");
+ std::string path;
+ const char *dirname = m_directory.GetCString();
+ const char *filename = m_filename.GetCString();
+ if (dirname)
+ {
+ path.append (dirname);
+ if (filename && m_directory != g_slash_only)
+ path.append ("/");
+ }
+ if (filename)
+ path.append (filename);
+ return path;
+}
+
ConstString
FileSpec::GetFileNameExtension () const
{
- const char *filename = m_filename.GetCString();
- if (filename == NULL)
- return ConstString();
-
- const char* dot_pos = strrchr(filename, '.');
- if (dot_pos == NULL)
- return ConstString();
-
- return ConstString(dot_pos+1);
+ if (m_filename)
+ {
+ const char *filename = m_filename.GetCString();
+ const char* dot_pos = strrchr(filename, '.');
+ if (dot_pos && dot_pos[1] != '\0')
+ return ConstString(dot_pos+1);
+ }
+ return ConstString();
}
ConstString
@@ -776,10 +764,11 @@ DataBufferSP
FileSpec::MemoryMapFileContents(off_t file_offset, size_t file_size) const
{
DataBufferSP data_sp;
- auto_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
+ std::unique_ptr<DataBufferMemoryMap> mmap_data(new DataBufferMemoryMap());
if (mmap_data.get())
{
- if (mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size) >= file_size)
+ const size_t mapped_length = mmap_data->MemoryMapFromFileSpec (this, file_offset, file_size);
+ if (((file_size == SIZE_MAX) && (mapped_length > 0)) || (mapped_length >= file_size))
data_sp.reset(mmap_data.release());
}
return data_sp;
@@ -846,7 +835,37 @@ FileSpec::ReadFileContents (off_t file_o
File file;
error = file.Open(resolved_path, File::eOpenOptionRead);
if (error.Success())
- error = file.Read (file_size, file_offset, data_sp);
+ {
+ const bool null_terminate = false;
+ error = file.Read (file_size, file_offset, null_terminate, data_sp);
+ }
+ }
+ else
+ {
+ error.SetErrorString("invalid file specification");
+ }
+ if (error_ptr)
+ *error_ptr = error;
+ return data_sp;
+}
+
+DataBufferSP
+FileSpec::ReadFileContentsAsCString(Error *error_ptr)
+{
+ Error error;
+ DataBufferSP data_sp;
+ char resolved_path[PATH_MAX];
+ if (GetPath(resolved_path, sizeof(resolved_path)))
+ {
+ File file;
+ error = file.Open(resolved_path, File::eOpenOptionRead);
+ if (error.Success())
+ {
+ off_t offset = 0;
+ size_t length = SIZE_MAX;
+ const bool null_terminate = true;
+ error = file.Read (length, offset, null_terminate, data_sp);
+ }
}
else
{
@@ -864,7 +883,7 @@ FileSpec::ReadFileLines (STLStringArray
char path[PATH_MAX];
if (GetPath(path, sizeof(path)))
{
- ifstream file_stream (path);
+ std::ifstream file_stream (path);
if (file_stream)
{
@@ -892,8 +911,15 @@ FileSpec::EnumerateDirectory
lldb_utility::CleanUp <DIR *, int> dir_path_dir (opendir(dir_path), NULL, closedir);
if (dir_path_dir.is_valid())
{
- struct dirent* dp;
- while ((dp = readdir(dir_path_dir.get())) != NULL)
+ long path_max = fpathconf (dirfd (dir_path_dir.get()), _PC_NAME_MAX);
+#if defined (__APPLE_) && defined (__DARWIN_MAXPATHLEN)
+ if (path_max < __DARWIN_MAXPATHLEN)
+ path_max = __DARWIN_MAXPATHLEN;
+#endif
+ struct dirent *buf, *dp;
+ buf = (struct dirent *) malloc (offsetof (struct dirent, d_name) + path_max + 1);
+
+ while (buf && readdir_r(dir_path_dir.get(), buf, &dp) == 0 && dp)
{
// Only search directories
if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
@@ -939,7 +965,6 @@ FileSpec::EnumerateDirectory
switch (result)
{
- default:
case eEnumerateDirectoryResultNext:
// Enumerate next entry in the current directory. We just
// exit this switch and will continue enumerating the
@@ -956,6 +981,8 @@ FileSpec::EnumerateDirectory
{
// The subdirectory returned Quit, which means to
// stop all directory enumerations at all levels.
+ if (buf)
+ free (buf);
return eEnumerateDirectoryResultQuit;
}
break;
@@ -963,14 +990,22 @@ FileSpec::EnumerateDirectory
case eEnumerateDirectoryResultExit: // Exit from the current directory at the current level.
// Exit from this directory level and tell parent to
// keep enumerating.
+ if (buf)
+ free (buf);
return eEnumerateDirectoryResultNext;
case eEnumerateDirectoryResultQuit: // Stop directory enumerations at any level
+ if (buf)
+ free (buf);
return eEnumerateDirectoryResultQuit;
}
}
}
}
+ if (buf)
+ {
+ free (buf);
+ }
}
}
// By default when exiting a directory, we tell the parent enumeration
@@ -1112,3 +1147,48 @@ FileSpec::RemoveLastPathComponent ()
else
SetFile(m_directory.GetCString(),resolve);
}
+//------------------------------------------------------------------
+/// Returns true if the filespec represents an implementation source
+/// file (files with a ".c", ".cpp", ".m", ".mm" (many more)
+/// extension).
+///
+/// @return
+/// \b true if the filespec represents an implementation source
+/// file, \b false otherwise.
+//------------------------------------------------------------------
+bool
+FileSpec::IsSourceImplementationFile () const
+{
+ ConstString extension (GetFileNameExtension());
+ if (extension)
+ {
+ static RegularExpression g_source_file_regex ("^(c|m|mm|cpp|c\\+\\+|cxx|cc|cp|s|asm|f|f77|f90|f95|f03|for|ftn|fpp|ada|adb|ads)$",
+ REG_EXTENDED | REG_ICASE);
+ return g_source_file_regex.Execute (extension.GetCString());
+ }
+ return false;
+}
+
+bool
+FileSpec::IsRelativeToCurrentWorkingDirectory () const
+{
+ const char *directory = m_directory.GetCString();
+ if (directory && directory[0])
+ {
+ // If the path doesn't start with '/' or '~', return true
+ switch (directory[0])
+ {
+ case '/':
+ case '~':
+ return false;
+ default:
+ return true;
+ }
+ }
+ else if (m_filename)
+ {
+ // No directory, just a basename, return true
+ return true;
+ }
+ return false;
+}
Modified: lldb/branches/lldb-platform-work/source/Host/common/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Host.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Host.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Host.cpp Thu Jun 6 19:06:43 2013
@@ -7,53 +7,61 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Host/Host.h"
-#include "lldb/Core/ArchSpec.h"
-#include "lldb/Core/ConstString.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Core/Log.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/ThreadSafeSTLMap.h"
-#include "lldb/Host/Config.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Mutex.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/TargetList.h"
-
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MachO.h"
+#include "lldb/lldb-python.h"
+// C includes
#include <dlfcn.h>
#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <netdb.h>
#include <pwd.h>
+#include <sys/sysctl.h>
#include <sys/types.h>
-
+#include <unistd.h>
#if defined (__APPLE__)
#include <dispatch/dispatch.h>
#include <libproc.h>
#include <mach-o/dyld.h>
-#include <sys/sysctl.h>
+#include <mach/mach_port.h>
-
-#elif defined (__linux__)
+#elif defined (__linux__) || defined(__FreeBSD_kernel__)
+/* Linux or the FreeBSD kernel with glibc (Debian KFreeBSD for example) */
#include <sys/wait.h>
#elif defined (__FreeBSD__)
#include <sys/wait.h>
-#include <sys/sysctl.h>
#include <pthread_np.h>
#endif
+#include "lldb/Host/Host.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ThreadSafeSTLMap.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/TargetList.h"
+
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MachO.h"
+#include "llvm/ADT/Twine.h"
+
+
+
+
+
using namespace lldb;
using namespace lldb_private;
@@ -88,7 +96,7 @@ Host::StartMonitoringChildProcess
info_ptr->monitor_signals = monitor_signals;
char thread_name[256];
- ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
+ ::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
thread = ThreadCreate (thread_name,
MonitorChildProcessThreadFunction,
info_ptr,
@@ -128,7 +136,7 @@ private:
static void *
MonitorChildProcessThreadFunction (void *arg)
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
const char *function = __FUNCTION__;
if (log)
log->Printf ("%s (arg = %p) thread starting...", function, arg);
@@ -143,16 +151,21 @@ MonitorChildProcessThreadFunction (void
delete info;
int status = -1;
- const int options = 0;
+#if defined (__FreeBSD__)
+ #define __WALL 0
+#endif
+ const int options = __WALL;
+
while (1)
{
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf("%s ::wait_pid (pid = %i, &status, options = %i)...", function, pid, options);
+ log->Printf("%s ::wait_pid (pid = %" PRIu64 ", &status, options = %i)...", function, pid, options);
// Wait for all child processes
::pthread_testcancel ();
- const lldb::pid_t wait_pid = ::waitpid (pid, &status, options);
+ // Get signals from all children with same process group of pid
+ const lldb::pid_t wait_pid = ::waitpid (-1*pid, &status, options);
::pthread_testcancel ();
if (wait_pid == -1)
@@ -160,9 +173,13 @@ MonitorChildProcessThreadFunction (void
if (errno == EINTR)
continue;
else
+ {
+ if (log)
+ log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno));
break;
+ }
}
- else if (wait_pid == pid)
+ else if (wait_pid > 0)
{
bool exited = false;
int signal = 0;
@@ -183,8 +200,10 @@ MonitorChildProcessThreadFunction (void
{
signal = WTERMSIG(status);
status_cstr = "SIGNALED";
- exited = true;
- exit_status = -1;
+ if (wait_pid == pid) {
+ exited = true;
+ exit_status = -1;
+ }
}
else
{
@@ -197,7 +216,7 @@ MonitorChildProcessThreadFunction (void
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
if (log)
- log->Printf ("%s ::waitpid (pid = %i, &status, options = %i) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
+ log->Printf ("%s ::waitpid (pid = %" PRIu64 ", &status, options = %i) => pid = %" PRIu64 ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
function,
wait_pid,
options,
@@ -211,15 +230,23 @@ MonitorChildProcessThreadFunction (void
{
bool callback_return = false;
if (callback)
- callback_return = callback (callback_baton, pid, exited, signal, exit_status);
+ callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status);
// If our process exited, then this thread should exit
- if (exited)
+ if (exited && wait_pid == pid)
+ {
+ if (log)
+ log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg);
break;
+ }
// If the callback returns true, it means this process should
// exit
if (callback_return)
+ {
+ if (log)
+ log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg);
break;
+ }
}
}
}
@@ -331,6 +358,11 @@ Host::GetArchitecture (SystemDefaultArch
g_host_arch_32.Clear();
g_host_arch_64.Clear();
+ // If the OS is Linux, "unknown" in the vendor slot isn't what we want
+ // for the default triple. It's probably an artifact of config.guess.
+ if (triple.getOS() == llvm::Triple::Linux && triple.getVendor() == llvm::Triple::UnknownVendor)
+ triple.setVendorName("");
+
switch (triple.getArch())
{
default:
@@ -339,9 +371,14 @@ Host::GetArchitecture (SystemDefaultArch
break;
case llvm::Triple::x86_64:
+ g_host_arch_64.SetTriple(triple);
+ g_supports_64 = true;
+ g_host_arch_32.SetTriple(triple.get32BitArchVariant());
+ g_supports_32 = true;
+ break;
+
case llvm::Triple::sparcv9:
case llvm::Triple::ppc64:
- case llvm::Triple::cellspu:
g_host_arch_64.SetTriple(triple);
g_supports_64 = true;
break;
@@ -370,15 +407,9 @@ Host::GetVendorString()
static ConstString g_vendor;
if (!g_vendor)
{
-#if defined (__APPLE__)
const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
const llvm::StringRef &str_ref = host_arch.GetTriple().getVendorName();
g_vendor.SetCStringWithLength(str_ref.data(), str_ref.size());
-#elif defined (__linux__)
- g_vendor.SetCString("gnu");
-#elif defined (__FreeBSD__)
- g_vendor.SetCString("freebsd");
-#endif
}
return g_vendor;
}
@@ -389,15 +420,9 @@ Host::GetOSString()
static ConstString g_os_string;
if (!g_os_string)
{
-#if defined (__APPLE__)
const ArchSpec &host_arch = GetArchitecture (eSystemDefaultArchitecture);
const llvm::StringRef &str_ref = host_arch.GetTriple().getOSName();
g_os_string.SetCStringWithLength(str_ref.data(), str_ref.size());
-#elif defined (__linux__)
- g_os_string.SetCString("linux");
-#elif defined (__FreeBSD__)
- g_os_string.SetCString("freebsd");
-#endif
}
return g_os_string;
}
@@ -424,7 +449,12 @@ lldb::tid_t
Host::GetCurrentThreadID()
{
#if defined (__APPLE__)
- return ::mach_thread_self();
+ // Calling "mach_port_deallocate()" bumps the reference count on the thread
+ // port, so we need to deallocate it. mach_task_self() doesn't bump the ref
+ // count.
+ thread_port_t thread_self = mach_thread_self();
+ mach_port_deallocate(mach_task_self(), thread_self);
+ return thread_self;
#elif defined(__FreeBSD__)
return lldb::tid_t(pthread_getthreadid_np());
#else
@@ -494,7 +524,8 @@ Host::WillTerminate ()
{
}
-#if !defined (__APPLE__) && !defined (__FreeBSD__) // see macosx/Host.mm
+#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__linux__) // see macosx/Host.mm
+
void
Host::ThreadCreated (const char *thread_name)
{
@@ -513,7 +544,7 @@ Host::GetEnvironment (StringList &env)
return 0;
}
-#endif
+#endif // #if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined (__linux__)
struct HostThreadCreateInfo
{
@@ -537,7 +568,7 @@ ThreadCreateTrampoline (thread_arg_t arg
thread_func_t thread_fptr = info->thread_fptr;
thread_arg_t thread_arg = info->thread_arg;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
if (log)
log->Printf("thread created");
@@ -600,92 +631,44 @@ Host::ThreadJoin (lldb::thread_t thread,
return err == 0;
}
-// rdar://problem/8153284
-// Fixed a crasher where during shutdown, loggings attempted to access the
-// thread name but the static map instance had already been destructed.
-// So we are using a ThreadSafeSTLMap POINTER, initializing it with a
-// pthread_once action. That map will get leaked.
-//
-// Another approach is to introduce a static guard object which monitors its
-// own destruction and raises a flag, but this incurs more overhead.
-
-static pthread_once_t g_thread_map_once = PTHREAD_ONCE_INIT;
-static ThreadSafeSTLMap<uint64_t, std::string> *g_thread_names_map_ptr;
-static void
-InitThreadNamesMap()
-{
- g_thread_names_map_ptr = new ThreadSafeSTLMap<uint64_t, std::string>();
-}
-
-//------------------------------------------------------------------
-// Control access to a static file thread name map using a single
-// static function to avoid a static constructor.
-//------------------------------------------------------------------
-static const char *
-ThreadNameAccessor (bool get, lldb::pid_t pid, lldb::tid_t tid, const char *name)
-{
- int success = ::pthread_once (&g_thread_map_once, InitThreadNamesMap);
- if (success != 0)
- return NULL;
-
- uint64_t pid_tid = ((uint64_t)pid << 32) | (uint64_t)tid;
-
- if (get)
- {
- // See if the thread name exists in our thread name pool
- std::string value;
- bool found_it = g_thread_names_map_ptr->GetValueForKey (pid_tid, value);
- if (found_it)
- return value.c_str();
- else
- return NULL;
- }
- else if (name)
- {
- // Set the thread name
- g_thread_names_map_ptr->SetValueForKey (pid_tid, std::string(name));
- }
- return NULL;
-}
-
-const char *
+std::string
Host::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
{
- const char *name = ThreadNameAccessor (true, pid, tid, NULL);
- if (name == NULL)
- {
+ std::string thread_name;
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
- // We currently can only get the name of a thread in the current process.
- if (pid == Host::GetCurrentProcessID())
+ // We currently can only get the name of a thread in the current process.
+ if (pid == Host::GetCurrentProcessID())
+ {
+ char pthread_name[1024];
+ if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
{
- char pthread_name[1024];
- if (::pthread_getname_np (::pthread_from_mach_thread_np (tid), pthread_name, sizeof(pthread_name)) == 0)
+ if (pthread_name[0])
{
- if (pthread_name[0])
- {
- // Set the thread in our string pool
- ThreadNameAccessor (false, pid, tid, pthread_name);
- // Get our copy of the thread name string
- name = ThreadNameAccessor (true, pid, tid, NULL);
- }
+ thread_name = pthread_name;
}
-
- if (name == NULL)
+ }
+ else
+ {
+ dispatch_queue_t current_queue = ::dispatch_get_current_queue ();
+ if (current_queue != NULL)
{
- dispatch_queue_t current_queue = ::dispatch_get_current_queue ();
- if (current_queue != NULL)
- name = dispatch_queue_get_label (current_queue);
+ const char *queue_name = dispatch_queue_get_label (current_queue);
+ if (queue_name && queue_name[0])
+ {
+ thread_name = queue_name;
+ }
}
}
-#endif
}
- return name;
+#endif
+ return thread_name;
}
-void
+bool
Host::SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name)
{
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
lldb::pid_t curr_pid = Host::GetCurrentProcessID();
lldb::tid_t curr_tid = Host::GetCurrentThreadID();
if (pid == LLDB_INVALID_PROCESS_ID)
@@ -694,14 +677,39 @@ Host::SetThreadName (lldb::pid_t pid, ll
if (tid == LLDB_INVALID_THREAD_ID)
tid = curr_tid;
-#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
// Set the pthread name if possible
if (pid == curr_pid && tid == curr_tid)
{
- ::pthread_setname_np (name);
+ if (::pthread_setname_np (name) == 0)
+ return true;
+ }
+ return false;
+#elif defined (__linux__)
+ void *fn = dlsym (RTLD_DEFAULT, "pthread_setname_np");
+ if (fn)
+ {
+ int (*pthread_setname_np_func)(pthread_t thread, const char *name);
+ *reinterpret_cast<void **> (&pthread_setname_np_func) = fn;
+
+ lldb::pid_t curr_pid = Host::GetCurrentProcessID();
+ lldb::tid_t curr_tid = Host::GetCurrentThreadID();
+
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ pid = curr_pid;
+
+ if (tid == LLDB_INVALID_THREAD_ID)
+ tid = curr_tid;
+
+ if (pid == curr_pid)
+ {
+ if (pthread_setname_np_func (tid, name) == 0)
+ return true;
+ }
}
+ return false;
+#else
+ return false;
#endif
- ThreadNameAccessor (false, pid, tid, name);
}
FileSpec
@@ -991,13 +999,6 @@ Host::GetLLDBPath (PathType path_type, F
case ePathTypePythonDir:
{
- // TODO: Anyone know how we can determine this for linux? Other systems?
- // For linux and FreeBSD we are currently assuming the
- // location of the lldb binary that contains this function is
- // the directory that will contain a python directory which
- // has our lldb module. This is how files get placed when
- // compiling with Makefiles.
-
static ConstString g_lldb_python_dir;
if (!g_lldb_python_dir)
{
@@ -1016,9 +1017,19 @@ Host::GetLLDBPath (PathType path_type, F
::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
}
#else
+ llvm::Twine python_version_dir;
+ python_version_dir = "/python"
+ + llvm::Twine(PY_MAJOR_VERSION)
+ + "."
+ + llvm::Twine(PY_MINOR_VERSION)
+ + "/site-packages";
+
// We may get our string truncated. Should we protect
// this with an assert?
- ::strncat(raw_path, "/python", sizeof(raw_path) - strlen(raw_path) - 1);
+
+ ::strncat(raw_path, python_version_dir.str().c_str(),
+ sizeof(raw_path) - strlen(raw_path) - 1);
+
#endif
FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
g_lldb_python_dir.SetCString(resolved_path);
@@ -1087,9 +1098,6 @@ Host::GetLLDBPath (PathType path_type, F
// TODO: where would user LLDB plug-ins be located on linux? Other systems?
return false;
}
- default:
- assert (!"Unhandled PathType");
- break;
}
return false;
@@ -1212,16 +1220,16 @@ Host::GetEffectiveGroupID ()
return getegid();
}
-#if !defined (__APPLE__) && !defined (__FreeBSD__)
+#if !defined (__APPLE__) && !defined(__linux__)
uint32_t
Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
{
process_infos.Clear();
return process_infos.GetSize();
}
-#endif
+#endif // #if !defined (__APPLE__) && !defined(__linux__)
-#if !defined (__APPLE__) && !defined (__FreeBSD__)
+#if !defined (__APPLE__) && !defined (__FreeBSD__) && !defined(__linux__)
bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
@@ -1230,6 +1238,14 @@ Host::GetProcessInfo (lldb::pid_t pid, P
}
#endif
+#if !defined(__linux__)
+bool
+Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
+{
+ return false;
+}
+#endif
+
lldb::TargetSP
Host::GetDummyTarget (lldb_private::Debugger &debugger)
{
@@ -1242,7 +1258,7 @@ Host::GetDummyTarget (lldb_private::Debu
if (!arch.IsValid())
arch = Host::GetArchitecture ();
Error err = debugger.GetTargetList().CreateTarget(debugger,
- FileSpec(),
+ NULL,
arch.GetTriple().getTriple().c_str(),
false,
NULL,
@@ -1300,30 +1316,31 @@ Host::RunShellCommand (const char *comma
int *status_ptr,
int *signo_ptr,
std::string *command_output_ptr,
- uint32_t timeout_sec)
+ uint32_t timeout_sec,
+ const char *shell)
{
Error error;
ProcessLaunchInfo launch_info;
-
- const bool localhost = true;
- const bool will_debug = false;
- const bool first_arg_is_full_shell_command = true;
-
-#ifndef LLDB_DEFAULT_SHELL_COMMAND
-#define LLDB_DEFAULT_SHELL_COMMAND "/bin/bash"
-#endif
- const char* shell_cmd = ::getenv("SHELL");
- if (shell_cmd == NULL)
- shell_cmd = LLDB_DEFAULT_SHELL_COMMAND;
-
- launch_info.SetShell(shell_cmd);
- launch_info.GetArguments().AppendArgument(command);
-
- if (!launch_info.ConvertArgumentsForLaunchingInShell (error,
- localhost,
- will_debug,
- first_arg_is_full_shell_command))
- return error;
+ if (shell && shell[0])
+ {
+ // Run the command in a shell
+ launch_info.SetShell(shell);
+ launch_info.GetArguments().AppendArgument(command);
+ const bool localhost = true;
+ const bool will_debug = false;
+ const bool first_arg_is_full_shell_command = true;
+ launch_info.ConvertArgumentsForLaunchingInShell (error,
+ localhost,
+ will_debug,
+ first_arg_is_full_shell_command);
+ }
+ else
+ {
+ // No shell, just run it
+ Args args (command);
+ const bool first_arg_is_executable = true;
+ launch_info.SetArguments(args, first_arg_is_executable);
+ }
if (working_dir)
launch_info.SetWorkingDirectory(working_dir);
@@ -1347,7 +1364,7 @@ Host::RunShellCommand (const char *comma
}
// The process monitor callback will delete the 'shell_info_ptr' below...
- std::auto_ptr<ShellInfo> shell_info_ap (new ShellInfo());
+ std::unique_ptr<ShellInfo> shell_info_ap (new ShellInfo());
const bool monitor_signals = false;
launch_info.SetMonitorProcessCallback(MonitorShellCommand, shell_info_ap.get(), monitor_signals);
@@ -1362,7 +1379,7 @@ Host::RunShellCommand (const char *comma
{
// The process successfully launched, so we can defer ownership of
// "shell_info" to the MonitorShellCommand callback function that will
- // get called when the process dies. We release the std::auto_ptr as it
+ // get called when the process dies. We release the unique pointer as it
// doesn't need to delete the ShellInfo anymore.
ShellInfo *shell_info = shell_info_ap.release();
TimeValue timeout_time(TimeValue::Now());
@@ -1420,6 +1437,52 @@ Host::RunShellCommand (const char *comma
}
+uint32_t
+Host::GetNumberCPUS ()
+{
+ static uint32_t g_num_cores = UINT32_MAX;
+ if (g_num_cores == UINT32_MAX)
+ {
+#if defined(__APPLE__) or defined (__linux__) or defined (__FreeBSD__)
+
+ g_num_cores = ::sysconf(_SC_NPROCESSORS_ONLN);
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+
+ // Header file for this might need to be included at the top of this file
+ SYSTEM_INFO system_info;
+ ::GetSystemInfo (&system_info);
+ g_num_cores = system_info.dwNumberOfProcessors;
+
+#else
+
+ // Assume POSIX support if a host specific case has not been supplied above
+ g_num_cores = 0;
+ int num_cores = 0;
+ size_t num_cores_len = sizeof(num_cores);
+ int mib[] = { CTL_HW, HW_AVAILCPU };
+
+ /* get the number of CPUs from the system */
+ if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
+ {
+ g_num_cores = num_cores;
+ }
+ else
+ {
+ mib[1] = HW_NCPU;
+ num_cores_len = sizeof(num_cores);
+ if (sysctl(mib, sizeof(mib)/sizeof(int), &num_cores, &num_cores_len, NULL, 0) == 0 && (num_cores > 0))
+ {
+ if (num_cores > 0)
+ g_num_cores = num_cores;
+ }
+ }
+#endif
+ }
+ return g_num_cores;
+}
+
+
#if !defined (__APPLE__)
bool
@@ -1461,80 +1524,108 @@ FDToFileMap& GetFDToFileMap()
lldb::user_id_t
Host::OpenFile (const FileSpec& file_spec,
uint32_t flags,
- mode_t mode)
+ mode_t mode,
+ Error &error)
{
- std::string path;
- if (file_spec.GetPath(path) == 0)
+ std::string path (file_spec.GetPath());
+ if (path.empty())
+ {
+ error.SetErrorString("empty path");
return UINT64_MAX;
- FileSP file_sp(new File(path.c_str(),flags,mode));
+ }
+ FileSP file_sp(new File());
+ error = file_sp->Open(path.c_str(),flags,mode);
if (file_sp->IsValid() == false)
return UINT64_MAX;
- uint32_t fd = file_sp->GetDescriptor();
+ lldb::user_id_t fd = file_sp->GetDescriptor();
GetFDToFileMap()[fd] = file_sp;
return fd;
}
bool
-Host::CloseFile (lldb::user_id_t fd)
+Host::CloseFile (lldb::user_id_t fd, Error &error)
{
if (fd == UINT64_MAX)
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return false;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat ("invalid host file descriptor %lli", fd);
return false;
- FDToFileMap::iterator i = GetFDToFileMap().find(fd),
- end = GetFDToFileMap().end();
- if (i == end)
+ }
+ FileSP file_sp = pos->second;
+ if (!file_sp)
+ {
+ error.SetErrorString ("invalid host backing file");
return false;
- FileSP file_sp = i->second;
- Error err;
- if (file_sp)
- err = file_sp->Close();
- GetFDToFileMap().erase(i);
- return err.Success();
+ }
+ error = file_sp->Close();
+ file_map.erase(pos);
+ return error.Success();
}
-uint32_t
-Host::WriteFile (lldb::user_id_t fd, uint64_t offset, void* data, size_t data_len)
+uint64_t
+Host::WriteFile (lldb::user_id_t fd, uint64_t offset, const void* src, uint64_t src_len, Error &error)
{
if (fd == UINT64_MAX)
- return UINT32_MAX;
- FDToFileMap::iterator i = GetFDToFileMap().find(fd),
- end = GetFDToFileMap().end();
- if (i == end)
- return UINT32_MAX;
- FileSP file_sp = i->second;
- off_t offset_ = offset;
- Error err = file_sp->SeekFromStart(offset_);
- if (err.Fail())
- return UINT32_MAX;
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat("invalid host file descriptor %lli", fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
if (!file_sp)
- return UINT32_MAX;
- size_t data_len_ = data_len;
- err = file_sp->Write(data,data_len_);
- if (err.Fail())
- return UINT32_MAX;
- return data_len_;
+ {
+ error.SetErrorString ("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_written = src_len;
+ error = file_sp->Write(src, bytes_written);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_written;
}
-uint32_t
-Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* data_ptr, size_t len_wanted)
+uint64_t
+Host::ReadFile (lldb::user_id_t fd, uint64_t offset, void* dst, uint64_t dst_len, Error &error)
{
if (fd == UINT64_MAX)
- return UINT32_MAX;
- FDToFileMap::iterator i = GetFDToFileMap().find(fd),
- end = GetFDToFileMap().end();
- if (i == end)
- return UINT32_MAX;
- FileSP file_sp = i->second;
- off_t offset_ = offset;
- Error err = file_sp->SeekFromStart(offset_);
- if (err.Fail())
- return UINT32_MAX;
+ {
+ error.SetErrorString ("invalid file descriptor");
+ return UINT64_MAX;
+ }
+ FDToFileMap& file_map = GetFDToFileMap();
+ FDToFileMap::iterator pos = file_map.find(fd);
+ if (pos == file_map.end())
+ {
+ error.SetErrorStringWithFormat ("invalid host file descriptor %lli", fd);
+ return false;
+ }
+ FileSP file_sp = pos->second;
if (!file_sp)
- return UINT32_MAX;
- size_t len_wanted_ = len_wanted;
- err = file_sp->Read(data_ptr,len_wanted_);
- if (err.Fail())
- return UINT32_MAX;
- return len_wanted_;
+ {
+ error.SetErrorString ("invalid host backing file");
+ return UINT64_MAX;
+ }
+ if (file_sp->SeekFromStart(offset, &error) != offset || error.Fail())
+ return UINT64_MAX;
+ size_t bytes_read = dst_len;
+ error = file_sp->Read(dst ,bytes_read);
+ if (error.Fail())
+ return UINT64_MAX;
+ return bytes_read;
}
lldb::user_id_t
@@ -1555,11 +1646,9 @@ Host::CalculateMD5 (const FileSpec& file
uint64_t &high)
{
#if defined (__APPLE__)
- std::string hash_string;
- file_spec.GetPath(hash_string);
StreamString md5_cmd_line;
- md5_cmd_line.Printf("md5 -q %s",hash_string.c_str());
- hash_string.clear();
+ md5_cmd_line.Printf("md5 -q '%s'", file_spec.GetPath().c_str());
+ std::string hash_string;
Error err = Host::RunShellCommand(md5_cmd_line.GetData(), NULL, NULL, NULL, &hash_string, 60);
if (err.Fail())
return false;
Modified: lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Mutex.cpp Thu Jun 6 19:06:43 2013
@@ -27,6 +27,7 @@
// Enable extra mutex error checking
#ifdef LLDB_CONFIGURATION_DEBUG
#define ENABLE_MUTEX_ERROR_CHECKING 1
+#include <inttypes.h>
#endif
#if ENABLE_MUTEX_ERROR_CHECKING
@@ -218,10 +219,6 @@ Mutex::Mutex (Mutex::Type type) :
case eMutexTypeRecursive:
err = ::pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
break;
-
- default:
- err = -1;
- break;
}
assert(err == 0);
err = ::pthread_mutex_init (&m_mutex, &attr);
@@ -241,8 +238,8 @@ Mutex::Mutex (Mutex::Type type) :
//----------------------------------------------------------------------
Mutex::~Mutex()
{
- int err;
- err = ::pthread_mutex_destroy (&m_mutex);
+ int err = ::pthread_mutex_destroy (&m_mutex);
+ assert(err == 0);
#if ENABLE_MUTEX_ERROR_CHECKING
if (err == 0)
error_check_mutex (&m_mutex, eMutexActionDestroyed);
@@ -275,7 +272,7 @@ Mutex::GetMutex()
int
Mutex::Lock()
{
- DEBUG_LOG ("[%4.4llx/%4.4llx] pthread_mutex_lock (%p)...\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex);
+ DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p)...\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex);
#if ENABLE_MUTEX_ERROR_CHECKING
error_check_mutex (&m_mutex, eMutexActionAssertInitialized);
@@ -291,7 +288,7 @@ Mutex::Lock()
assert(err == 0);
}
#endif
- DEBUG_LOG ("[%4.4llx/%4.4llx] pthread_mutex_lock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
+ DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_lock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
return err;
}
@@ -311,7 +308,7 @@ Mutex::TryLock(const char *failure_messa
#endif
int err = ::pthread_mutex_trylock (&m_mutex);
- DEBUG_LOG ("[%4.4llx/%4.4llx] pthread_mutex_trylock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
+ DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_trylock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
return err;
}
@@ -340,7 +337,7 @@ Mutex::Unlock()
assert(err == 0);
}
#endif
- DEBUG_LOG ("[%4.4llx/%4.4llx] pthread_mutex_unlock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
+ DEBUG_LOG ("[%4.4" PRIx64 "/%4.4" PRIx64 "] pthread_mutex_unlock (%p) => %i\n", Host::GetCurrentProcessID(), Host::GetCurrentThreadID(), &m_mutex, err);
return err;
}
@@ -356,6 +353,38 @@ TrackingMutex::Unlock ()
assert (m_failure_message.empty());
return Mutex::Unlock();
}
+
+int
+LoggingMutex::Lock ()
+{
+ printf("locking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
+ int x = Mutex::Lock();
+ m_locked = true;
+ printf("%d\n",x);
+ return x;
+}
+
+int
+LoggingMutex::Unlock ()
+{
+ printf("unlocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
+ int x = Mutex::Unlock();
+ m_locked = false;
+ printf("%d\n",x);
+ return x;
+}
+
+int
+LoggingMutex::TryLock (const char *failure_message)
+{
+ printf("trylocking mutex %p by [%4.4" PRIx64 "/%4.4" PRIx64 "]...", this, Host::GetCurrentProcessID(), Host::GetCurrentThreadID());
+ int x = Mutex::TryLock(failure_message);
+ if (x == 0)
+ m_locked = true;
+ printf("%d\n",x);
+ return x;
+}
+
#endif
-
+
Modified: lldb/branches/lldb-platform-work/source/Host/common/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Symbols.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Symbols.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Symbols.cpp Thu Jun 6 19:06:43 2013
@@ -28,4 +28,21 @@ Symbols::LocateExecutableSymbolFile (con
return FileSpec();
}
+FileSpec
+Symbols::FindSymbolFileInBundle (const FileSpec& symfile_bundle,
+ const lldb_private::UUID *uuid,
+ const ArchSpec *arch)
+{
+ return FileSpec();
+}
+
+bool
+Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
+{
+ // Fill in the module_spec.GetFileSpec() for the object file and/or the
+ // module_spec.GetSymbolFileSpec() for the debug symbols file.
+ return false;
+}
+
+
#endif
Modified: lldb/branches/lldb-platform-work/source/Host/common/Terminal.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/common/Terminal.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/common/Terminal.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/common/Terminal.cpp Thu Jun 6 19:06:43 2013
@@ -120,6 +120,15 @@ TerminalState::~TerminalState()
{
}
+void
+TerminalState::Clear ()
+{
+ m_tty.Clear();
+ m_tflags = -1;
+ m_termios_ap.reset();
+ m_process_group = -1;
+}
+
//----------------------------------------------------------------------
// Save the current state of the TTY for the file descriptor "fd"
// and if "save_process_group" is true, attempt to save the process
Modified: lldb/branches/lldb-platform-work/source/Host/freebsd/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/freebsd/Host.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/freebsd/Host.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/freebsd/Host.cpp Thu Jun 6 19:06:43 2013
@@ -377,14 +377,14 @@ GetFreeBSDProcessArgs (const ProcessInst
{
if (process_info.ProcessIDIsValid())
{
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() };
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
char arg_data[8192];
size_t arg_data_size = sizeof(arg_data);
if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
{
DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
const char *cstr;
cstr = data.GetCStr (&offset);
@@ -443,7 +443,7 @@ GetFreeBSDProcessUserAndGroup(ProcessIns
if (process_info.ProcessIDIsValid())
{
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
- process_info.GetProcessID() };
+ (int)process_info.GetProcessID() };
proc_kinfo_size = sizeof(struct kinfo_proc);
if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
@@ -573,14 +573,14 @@ Host::GetAuxvData(lldb_private::Process
struct ps_strings ps_strings;
struct ptrace_io_desc pid;
DataBufferSP buf_sp;
- std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+ std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
pid.piod_op = PIOD_READ_D;
pid.piod_addr = &ps_strings;
pid.piod_offs = ps_strings_addr;
pid.piod_len = sizeof(ps_strings);
- if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
perror("failed to fetch ps_strings");
buf_ap.release();
goto done;
@@ -591,7 +591,7 @@ Host::GetAuxvData(lldb_private::Process
pid.piod_addr = aux_info;
pid.piod_offs = auxv_addr;
pid.piod_len = sizeof(aux_info);
- if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) {
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
perror("failed to fetch aux_info");
buf_ap.release();
goto done;
Modified: lldb/branches/lldb-platform-work/source/Host/linux/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/linux/Host.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/linux/Host.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/linux/Host.cpp Thu Jun 6 19:06:43 2013
@@ -12,9 +12,9 @@
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
#include <fcntl.h>
-
// C++ Includes
// Other libraries and framework includes
// Project includes
@@ -25,12 +25,184 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Symbol/ObjectFile.h"
+
using namespace lldb;
using namespace lldb_private;
+typedef enum ProcessStateFlags
+{
+ eProcessStateRunning = (1u << 0), // Running
+ eProcessStateSleeping = (1u << 1), // Sleeping in an interruptible wait
+ eProcessStateWaiting = (1u << 2), // Waiting in an uninterruptible disk sleep
+ eProcessStateZombie = (1u << 3), // Zombie
+ eProcessStateTracedOrStopped = (1u << 4), // Traced or stopped (on a signal)
+ eProcessStatePaging = (1u << 5) // Paging
+} ProcessStateFlags;
+
+typedef struct ProcessStatInfo
+{
+ lldb::pid_t ppid; // Parent Process ID
+ uint32_t fProcessState; // ProcessStateFlags
+} ProcessStatInfo;
+
+// Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
+static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);
+
+
+namespace
+{
+
+lldb::DataBufferSP
+ReadProcPseudoFile (lldb::pid_t pid, const char *name)
+{
+ int fd;
+ char path[PATH_MAX];
+
+ // Make sure we've got a nil terminated buffer for all the folks calling
+ // GetBytes() directly off our returned DataBufferSP if we hit an error.
+ lldb::DataBufferSP buf_sp (new DataBufferHeap(1, 0));
+
+ // Ideally, we would simply create a FileSpec and call ReadFileContents.
+ // However, files in procfs have zero size (since they are, in general,
+ // dynamically generated by the kernel) which is incompatible with the
+ // current ReadFileContents implementation. Therefore we simply stream the
+ // data into a DataBuffer ourselves.
+ if (snprintf (path, PATH_MAX, "/proc/%" PRIu64 "/%s", pid, name) > 0)
+ {
+ if ((fd = open (path, O_RDONLY, 0)) >= 0)
+ {
+ size_t bytes_read = 0;
+ std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+
+ for (;;)
+ {
+ size_t avail = buf_ap->GetByteSize() - bytes_read;
+ ssize_t status = read (fd, buf_ap->GetBytes() + bytes_read, avail);
+
+ if (status < 0)
+ break;
+
+ if (status == 0)
+ {
+ buf_ap->SetByteSize (bytes_read);
+ buf_sp.reset (buf_ap.release());
+ break;
+ }
+
+ bytes_read += status;
+
+ if (avail - status == 0)
+ buf_ap->SetByteSize (2 * buf_ap->GetByteSize());
+ }
+
+ close (fd);
+ }
+ }
+
+ return buf_sp;
+}
+
+} // anonymous namespace
+
+static bool
+ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info)
+{
+ // Read the /proc/$PID/stat file.
+ lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "stat");
+
+ // The filename of the executable is stored in parenthesis right after the pid. We look for the closing
+ // parenthesis for the filename and work from there in case the name has something funky like ')' in it.
+ const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')');
+ if (filename_end)
+ {
+ char state = '\0';
+ int ppid = LLDB_INVALID_PROCESS_ID;
+
+ // Read state and ppid.
+ sscanf (filename_end + 1, " %c %d", &state, &ppid);
+
+ stat_info.ppid = ppid;
+
+ switch (state)
+ {
+ case 'R':
+ stat_info.fProcessState |= eProcessStateRunning;
+ break;
+ case 'S':
+ stat_info.fProcessState |= eProcessStateSleeping;
+ break;
+ case 'D':
+ stat_info.fProcessState |= eProcessStateWaiting;
+ break;
+ case 'Z':
+ stat_info.fProcessState |= eProcessStateZombie;
+ break;
+ case 'T':
+ stat_info.fProcessState |= eProcessStateTracedOrStopped;
+ break;
+ case 'W':
+ stat_info.fProcessState |= eProcessStatePaging;
+ break;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static void
+GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid)
+{
+ tracerpid = 0;
+ uint32_t rUid = UINT32_MAX; // Real User ID
+ uint32_t eUid = UINT32_MAX; // Effective User ID
+ uint32_t rGid = UINT32_MAX; // Real Group ID
+ uint32_t eGid = UINT32_MAX; // Effective Group ID
+
+ // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields.
+ lldb::DataBufferSP buf_sp = ReadProcPseudoFile (pid, "status");
+
+ static const char uid_token[] = "Uid:";
+ char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token);
+ if (buf_uid)
+ {
+ // Real, effective, saved set, and file system UIDs. Read the first two.
+ buf_uid += sizeof(uid_token);
+ rUid = strtol (buf_uid, &buf_uid, 10);
+ eUid = strtol (buf_uid, &buf_uid, 10);
+ }
+
+ static const char gid_token[] = "Gid:";
+ char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token);
+ if (buf_gid)
+ {
+ // Real, effective, saved set, and file system GIDs. Read the first two.
+ buf_gid += sizeof(gid_token);
+ rGid = strtol (buf_gid, &buf_gid, 10);
+ eGid = strtol (buf_gid, &buf_gid, 10);
+ }
+
+ static const char tracerpid_token[] = "TracerPid:";
+ char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token);
+ if (buf_tracerpid)
+ {
+ // Tracer PID. 0 if we're not being debugged.
+ buf_tracerpid += sizeof(tracerpid_token);
+ tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10);
+ }
+
+ process_info.SetUserID (rUid);
+ process_info.SetEffectiveUserID (eUid);
+ process_info.SetGroupID (rGid);
+ process_info.SetEffectiveGroupID (eGid);
+}
+
bool
-Host::GetOSVersion(uint32_t &major,
- uint32_t &minor,
+Host::GetOSVersion(uint32_t &major,
+ uint32_t &minor,
uint32_t &update)
{
struct utsname un;
@@ -40,7 +212,7 @@ Host::GetOSVersion(uint32_t &major,
return false;
status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
- return status == 3;
+ return status == 3;
}
Error
@@ -54,45 +226,261 @@ Host::LaunchProcess (ProcessLaunchInfo &
lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
- static const size_t path_size = 128;
- static char path[path_size];
- lldb::DataBufferSP buf_sp;
+ return ReadProcPseudoFile(process->GetID(), "auxv");
+}
- int fd;
+static bool
+IsDirNumeric(const char *dname)
+{
+ for (; *dname; dname++)
+ {
+ if (!isdigit (*dname))
+ return false;
+ }
+ return true;
+}
- // Ideally, we would simply create a FileSpec and call ReadFileContents.
- // However, files in procfs have zero size (since they are, in general,
- // dynamically generated by the kernel) which is incompatible with the
- // current ReadFileContents implementation. Therefore we simply stream the
- // data into a DataBuffer ourselves.
- if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0)
- return buf_sp;
+uint32_t
+Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
+{
+ static const char procdir[] = "/proc/";
+
+ DIR *dirproc = opendir (procdir);
+ if (dirproc)
+ {
+ struct dirent *direntry = NULL;
+ const uid_t our_uid = getuid();
+ const lldb::pid_t our_pid = getpid();
+ bool all_users = match_info.GetMatchAllUsers();
+
+ while ((direntry = readdir (dirproc)) != NULL)
+ {
+ if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
+ continue;
- if ((fd = open(path, O_RDONLY, 0)) < 0)
- return buf_sp;
+ lldb::pid_t pid = atoi (direntry->d_name);
+
+ // Skip this process.
+ if (pid == our_pid)
+ continue;
+
+ lldb::pid_t tracerpid;
+ ProcessStatInfo stat_info;
+ ProcessInstanceInfo process_info;
+
+ if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid))
+ continue;
+
+ // Skip if process is being debugged.
+ if (tracerpid != 0)
+ continue;
+
+ // Skip zombies.
+ if (stat_info.fProcessState & eProcessStateZombie)
+ continue;
+
+ // Check for user match if we're not matching all users and not running as root.
+ if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
+ continue;
+
+ if (match_info.Matches (process_info))
+ {
+ process_infos.Append (process_info);
+ }
+ }
+
+ closedir (dirproc);
+ }
- size_t bytes_read = 0;
- std::auto_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
- for (;;)
+ return process_infos.GetSize();
+}
+
+bool
+Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
+{
+ bool tids_changed = false;
+ static const char procdir[] = "/proc/";
+ static const char taskdir[] = "/task/";
+ std::string process_task_dir = procdir + std::to_string(pid) + taskdir;
+ DIR *dirproc = opendir (process_task_dir.c_str());
+
+ if (dirproc)
{
- size_t avail = buf_ap->GetByteSize() - bytes_read;
- ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
+ struct dirent *direntry = NULL;
+ while ((direntry = readdir (dirproc)) != NULL)
+ {
+ if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
+ continue;
- if (status < 0)
- break;
+ lldb::tid_t tid = atoi(direntry->d_name);
+ TidMap::iterator it = tids_to_attach.find(tid);
+ if (it == tids_to_attach.end())
+ {
+ tids_to_attach.insert(TidPair(tid, false));
+ tids_changed = true;
+ }
+ }
+ closedir (dirproc);
+ }
- bytes_read += status;
+ return tids_changed;
+}
+
+static bool
+GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info)
+{
+ // Clear the architecture.
+ process_info.GetArchitecture().Clear();
- if (status == 0)
+ ModuleSpecList specs;
+ FileSpec filespec (exe_path, false);
+ const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, specs);
+ // GetModuleSpecifications() could fail if the executable has been deleted or is locked.
+ // But it shouldn't return more than 1 architecture.
+ assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
+ if (num_specs == 1)
+ {
+ ModuleSpec module_spec;
+ if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid())
{
- buf_ap->SetByteSize(bytes_read);
- buf_sp.reset(buf_ap.release());
- break;
+ process_info.GetArchitecture () = module_spec.GetArchitecture();
+ return true;
}
+ }
+ return false;
+}
+
+static bool
+GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid)
+{
+ tracerpid = 0;
+ process_info.Clear();
+ ::memset (&stat_info, 0, sizeof(stat_info));
+ stat_info.ppid = LLDB_INVALID_PROCESS_ID;
+
+ // Use special code here because proc/[pid]/exe is a symbolic link.
+ char link_path[PATH_MAX];
+ char exe_path[PATH_MAX] = "";
+ if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0)
+ return false;
+
+ ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1);
+ if (len <= 0)
+ return false;
+
+ // readlink does not append a null byte.
+ exe_path[len] = 0;
- if (avail - status == 0)
- buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
+ // If the binary has been deleted, the link name has " (deleted)" appended.
+ // Remove if there.
+ static const ssize_t deleted_len = strlen(" (deleted)");
+ if (len > deleted_len &&
+ !strcmp(exe_path + len - deleted_len, " (deleted)"))
+ {
+ exe_path[len - deleted_len] = 0;
+ }
+ else
+ {
+ GetELFProcessCPUType (exe_path, process_info);
}
- return buf_sp;
+ process_info.SetProcessID(pid);
+ process_info.GetExecutableFile().SetFile(exe_path, false);
+
+ lldb::DataBufferSP buf_sp;
+
+ // Get the process environment.
+ buf_sp = ReadProcPseudoFile(pid, "environ");
+ Args &info_env = process_info.GetEnvironmentEntries();
+ char *next_var = (char *)buf_sp->GetBytes();
+ char *end_buf = next_var + buf_sp->GetByteSize();
+ while (next_var < end_buf && 0 != *next_var)
+ {
+ info_env.AppendArgument(next_var);
+ next_var += strlen(next_var) + 1;
+ }
+
+ // Get the commond line used to start the process.
+ buf_sp = ReadProcPseudoFile(pid, "cmdline");
+
+ // Grab Arg0 first.
+ char *cmd = (char *)buf_sp->GetBytes();
+ process_info.SetArg0(cmd);
+
+ // Now process any remaining arguments.
+ Args &info_args = process_info.GetArguments();
+ char *next_arg = cmd + strlen(cmd) + 1;
+ end_buf = cmd + buf_sp->GetByteSize();
+ while (next_arg < end_buf && 0 != *next_arg)
+ {
+ info_args.AppendArgument(next_arg);
+ next_arg += strlen(next_arg) + 1;
+ }
+
+ // Read /proc/$PID/stat to get our parent pid.
+ if (ReadProcPseudoFileStat (pid, stat_info))
+ {
+ process_info.SetParentProcessID (stat_info.ppid);
+ }
+
+ // Get User and Group IDs and get tracer pid.
+ GetLinuxProcessUserAndGroup (pid, process_info, tracerpid);
+
+ return true;
+}
+
+bool
+Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ lldb::pid_t tracerpid;
+ ProcessStatInfo stat_info;
+
+ return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid);
+}
+
+void
+Host::ThreadCreated (const char *thread_name)
+{
+ if (!Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name))
+ {
+ // pthread_setname_np_func can fail if the thread name is longer than
+ // the supported limit on Linux. When this occurs, the error ERANGE is returned
+ // and SetThreadName will fail. Let's drop it down to 16 characters and try again.
+ char namebuf[16];
+
+ // Thread names are coming in like '<lldb.comm.debugger.edit>' and '<lldb.comm.debugger.editline>'
+ // So just chopping the end of the string off leads to a lot of similar named threads.
+ // Go through the thread name and search for the last dot and use that.
+ const char *lastdot = ::strrchr( thread_name, '.' );
+
+ if (lastdot && lastdot != thread_name)
+ thread_name = lastdot + 1;
+ ::strncpy (namebuf, thread_name, sizeof(namebuf));
+ namebuf[ sizeof(namebuf) - 1 ] = 0;
+
+ int namebuflen = strlen(namebuf);
+ if (namebuflen > 0)
+ {
+ if (namebuf[namebuflen - 1] == '(' || namebuf[namebuflen - 1] == '>')
+ {
+ // Trim off trailing '(' and '>' characters for a bit more cleanup.
+ namebuflen--;
+ namebuf[namebuflen] = 0;
+ }
+ Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, namebuf);
+ }
+ }
+}
+
+void
+Host::Backtrace (Stream &strm, uint32_t max_frames)
+{
+ // TODO: Is there a way to backtrace the current process on linux?
+}
+
+size_t
+Host::GetEnvironment (StringList &env)
+{
+ // TODO: Is there a way to the host environment for this process on linux?
+ return 0;
}
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/Host.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/Host.mm?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/Host.mm (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/Host.mm Thu Jun 6 19:06:43 2013
@@ -502,9 +502,8 @@ LaunchInNewTerminalWithAppleScript (cons
if (!darwin_debug_file_spec.Exists())
{
- error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at %s/%s",
- darwin_debug_file_spec.GetDirectory().GetCString(),
- darwin_debug_file_spec.GetFilename().GetCString());
+ error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at '%s'",
+ darwin_debug_file_spec.GetPath().c_str());
return error;
}
@@ -523,10 +522,42 @@ LaunchInNewTerminalWithAppleScript (cons
const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir)
command.Printf(" --working-dir '%s'", working_dir);
+ else
+ {
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, PATH_MAX))
+ command.Printf(" --working-dir '%s'", cwd);
+ }
if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
command.PutCString(" --disable-aslr");
+ // We are launching on this host in a terminal. So compare the environemnt on the host
+ // to what is supplied in the launch_info. Any items that aren't in the host environemnt
+ // need to be sent to darwin-debug. If we send all environment entries, we might blow the
+ // max command line length, so we only send user modified entries.
+ const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector ();
+ StringList host_env;
+ const size_t host_env_count = Host::GetEnvironment (host_env);
+ const char *env_entry;
+ for (size_t env_idx = 0; (env_entry = envp[env_idx]) != NULL; ++env_idx)
+ {
+ bool add_entry = true;
+ for (size_t i=0; i<host_env_count; ++i)
+ {
+ const char *host_env_entry = host_env.GetStringAtIndex(i);
+ if (strcmp(env_entry, host_env_entry) == 0)
+ {
+ add_entry = false;
+ break;
+ }
+ }
+ if (add_entry)
+ {
+ command.Printf(" --env='%s'", env_entry);
+ }
+ }
+
command.PutCString(" -- ");
const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
@@ -681,7 +712,7 @@ Host::OpenFileInExternalEditor (const Fi
uint32_t reserved2; // must be zero
} BabelAESelInfo;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST));
char file_path[PATH_MAX];
file_spec.GetPath(file_path, PATH_MAX);
CFCString file_cfstr (file_path, kCFStringEncodingUTF8);
@@ -1039,14 +1070,24 @@ GetMacOSXProcessCPUType (ProcessInstance
mib_len++;
cpu_type_t cpu, sub = 0;
- size_t cpu_len = sizeof(cpu);
- if (::sysctl (mib, mib_len, &cpu, &cpu_len, 0, 0) == 0)
+ size_t len = sizeof(cpu);
+ if (::sysctl (mib, mib_len, &cpu, &len, 0, 0) == 0)
{
switch (cpu)
{
case llvm::MachO::CPUTypeI386: sub = llvm::MachO::CPUSubType_I386_ALL; break;
case llvm::MachO::CPUTypeX86_64: sub = llvm::MachO::CPUSubType_X86_64_ALL; break;
- default: break;
+ case llvm::MachO::CPUTypeARM:
+ {
+ uint32_t cpusubtype = 0;
+ len = sizeof(cpusubtype);
+ if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
+ sub = cpusubtype;
+ }
+ break;
+
+ default:
+ break;
}
process_info.GetArchitecture ().SetArchitecture (eArchTypeMachO, cpu, sub);
return true;
@@ -1069,7 +1110,7 @@ GetMacOSXProcessArgs (const ProcessInsta
if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
{
DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
uint32_t argc = data.GetU32 (&offset);
const char *cstr;
@@ -1291,7 +1332,7 @@ static Error
getXPCAuthorization (ProcessLaunchInfo &launch_info)
{
Error error;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
if ((launch_info.GetUserID() == 0) && !authorizationRef)
{
@@ -1302,7 +1343,7 @@ getXPCAuthorization (ProcessLaunchInfo &
error.SetErrorString("Can't create authorizationRef.");
if (log)
{
- error.PutToLog(log.get(), "%s", error.AsCString());
+ error.PutToLog(log, "%s", error.AsCString());
}
return error;
}
@@ -1343,7 +1384,7 @@ getXPCAuthorization (ProcessLaunchInfo &
error.SetErrorStringWithFormat("Launching as root needs root authorization.");
if (log)
{
- error.PutToLog(log.get(), "%s", error.AsCString());
+ error.PutToLog(log, "%s", error.AsCString());
}
if (authorizationRef)
@@ -1366,8 +1407,8 @@ LaunchProcessXPC (const char *exe_path,
if (error.Fail())
return error;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
-
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+
uid_t requested_uid = launch_info.GetUserID();
const char *xpc_service = nil;
bool send_auth = false;
@@ -1384,11 +1425,11 @@ LaunchProcessXPC (const char *exe_path,
}
else
{
- error.SetError(4, eErrorTypeGeneric);
+ error.SetError(3, eErrorTypeGeneric);
error.SetErrorStringWithFormat("Launching root via XPC needs to externalize authorization reference.");
if (log)
{
- error.PutToLog(log.get(), "%s", error.AsCString());
+ error.PutToLog(log, "%s", error.AsCString());
}
return error;
}
@@ -1396,11 +1437,11 @@ LaunchProcessXPC (const char *exe_path,
}
else
{
- error.SetError(3, eErrorTypeGeneric);
+ error.SetError(4, eErrorTypeGeneric);
error.SetErrorStringWithFormat("Launching via XPC is only currently available for either the login user or root.");
if (log)
{
- error.PutToLog(log.get(), "%s", error.AsCString());
+ error.PutToLog(log, "%s", error.AsCString());
}
return error;
}
@@ -1412,7 +1453,7 @@ LaunchProcessXPC (const char *exe_path,
if (type == XPC_TYPE_ERROR) {
if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
- // The service has either canceled itself, crashed, or been terminated.
+ // The service has either canceled itself, crashed, or been terminated.
// The XPC connection is still valid and sending a message to it will re-launch the service.
// If the service is state-full, this is the time to initialize the new service.
return;
@@ -1425,12 +1466,12 @@ LaunchProcessXPC (const char *exe_path,
// printf("Unexpected error from service: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
}
- } else {
+ } else {
// printf("Received unexpected event in handler");
}
});
- xpc_connection_set_finalizer_f (conn, xpc_finalizer_t(xpc_release));
+ xpc_connection_set_finalizer_f (conn, xpc_finalizer_t(xpc_release));
xpc_connection_resume (conn);
xpc_object_t message = xpc_dictionary_create (nil, nil, 0);
@@ -1447,24 +1488,36 @@ LaunchProcessXPC (const char *exe_path,
xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, GetPosixspawnFlags(launch_info));
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message);
-
- pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey);
- if (pid == 0)
+ xpc_type_t returnType = xpc_get_type(reply);
+ if (returnType == XPC_TYPE_DICTIONARY)
{
- int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey);
- int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey);
-
- error.SetError(errorCode, eErrorTypeGeneric);
- error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode);
- if (log)
+ pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey);
+ if (pid == 0)
{
- error.PutToLog(log.get(), "%s", error.AsCString());
+ int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey);
+ int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey);
+
+ error.SetError(errorCode, eErrorTypeGeneric);
+ error.SetErrorStringWithFormat("Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode);
+ if (log)
+ {
+ error.PutToLog(log, "%s", error.AsCString());
+ }
+
+ if (authorizationRef)
+ {
+ AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
+ authorizationRef = NULL;
+ }
}
-
- if (authorizationRef)
+ }
+ else if (returnType == XPC_TYPE_ERROR)
+ {
+ error.SetError(5, eErrorTypeGeneric);
+ error.SetErrorStringWithFormat("Problems with launching via XPC. XPC error : %s", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION));
+ if (log)
{
- AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
- authorizationRef = NULL;
+ error.PutToLog(log, "%s", error.AsCString());
}
}
@@ -1479,13 +1532,13 @@ static Error
LaunchProcessPosixSpawn (const char *exe_path, ProcessLaunchInfo &launch_info, ::pid_t &pid)
{
Error error;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
posix_spawnattr_t attr;
error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnattr_init ( &attr )");
+ error.PutToLog(log, "::posix_spawnattr_init ( &attr )");
if (error.Fail())
return error;
@@ -1503,7 +1556,7 @@ LaunchProcessPosixSpawn (const char *exe
short flags = GetPosixspawnFlags(launch_info);
error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
+ error.PutToLog(log, "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags);
if (error.Fail())
return error;
@@ -1521,7 +1574,7 @@ LaunchProcessPosixSpawn (const char *exe
size_t ocount = 0;
error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu, ocount);
+ error.PutToLog(log, "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu, (uint64_t)ocount);
if (error.Fail() || ocount != 1)
return error;
@@ -1542,7 +1595,6 @@ LaunchProcessPosixSpawn (const char *exe
argv = (char * const*)tmp_argv;
}
-
const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir)
{
@@ -1565,7 +1617,7 @@ LaunchProcessPosixSpawn (const char *exe
posix_spawn_file_actions_t file_actions;
error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawn_file_actions_init ( &file_actions )");
+ error.PutToLog(log, "::posix_spawn_file_actions_init ( &file_actions )");
if (error.Fail())
return error;
@@ -1580,7 +1632,7 @@ LaunchProcessPosixSpawn (const char *exe
{
if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
launch_file_action,
- log.get(),
+ log,
error))
return error;
}
@@ -1595,13 +1647,21 @@ LaunchProcessPosixSpawn (const char *exe
eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
+ {
+ error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
pid,
exe_path,
&file_actions,
&attr,
argv,
envp);
+ if (log)
+ {
+ for (int ii=0; argv[ii]; ++ii)
+ log->Printf("argv[%i] = '%s'", ii, argv[ii]);
+ }
+ }
+
}
else
{
@@ -1614,12 +1674,19 @@ LaunchProcessPosixSpawn (const char *exe
eErrorTypePOSIX);
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
+ {
+ error.PutToLog(log, "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
pid,
exe_path,
&attr,
argv,
envp);
+ if (log)
+ {
+ for (int ii=0; argv[ii]; ++ii)
+ log->Printf("argv[%i] = '%s'", ii, argv[ii]);
+ }
+ }
}
if (working_dir)
@@ -1754,7 +1821,7 @@ Host::StartMonitoringChildProcess (Host:
if (monitor_signals)
mask |= DISPATCH_PROC_SIGNAL;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
dispatch_source_t source = ::dispatch_source_create (DISPATCH_SOURCE_TYPE_PROC,
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/Symbols.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/Symbols.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/Symbols.cpp Thu Jun 6 19:06:43 2013
@@ -11,6 +11,7 @@
// C Includes
#include <dirent.h>
+#include <pwd.h>
#include "llvm/Support/MachO.h"
// C++ Includes
@@ -22,12 +23,15 @@
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/UUID.h"
#include "lldb/Host/Endian.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/CleanUp.h"
#include "Host/macosx/cfcpp/CFCBundle.h"
+#include "Host/macosx/cfcpp/CFCData.h"
#include "Host/macosx/cfcpp/CFCReleaser.h"
#include "Host/macosx/cfcpp/CFCString.h"
#include "mach/machine.h"
@@ -54,7 +58,7 @@ SkinnyMachOFileContainsArchAndUUID
const lldb_private::UUID *uuid, // the UUID we are looking for
off_t file_offset,
DataExtractor& data,
- uint32_t data_offset,
+ lldb::offset_t data_offset,
const uint32_t magic
)
{
@@ -79,7 +83,7 @@ SkinnyMachOFileContainsArchAndUUID
{
ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);
- if (file_arch != *arch)
+ if (!file_arch.IsCompatibleMatch(*arch))
return false;
}
@@ -112,7 +116,7 @@ SkinnyMachOFileContainsArchAndUUID
for (i=0; i<ncmds; i++)
{
- const uint32_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry!
+ const lldb::offset_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry!
uint32_t cmd = data.GetU32(&data_offset);
uint32_t cmd_size = data.GetU32(&data_offset);
if (cmd == LoadCommandUUID)
@@ -120,15 +124,6 @@ SkinnyMachOFileContainsArchAndUUID
lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
if (file_uuid == *uuid)
return true;
-
- // Emit some warning messages since the UUIDs do not match!
- char path_buf[PATH_MAX];
- path_buf[0] = '\0';
- const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf
- : file_spec.GetFilename().AsCString();
- Host::SystemLog (Host::eSystemLogWarning,
- "warning: UUID mismatch detected between binary and:\n\t'%s'\n",
- path);
return false;
}
data_offset = cmd_offset + cmd_size;
@@ -144,7 +139,7 @@ UniversalMachOFileContainsArchAndUUID
const lldb_private::UUID *uuid,
off_t file_offset,
DataExtractor& data,
- uint32_t data_offset,
+ lldb::offset_t data_offset,
const uint32_t magic
)
{
@@ -174,7 +169,7 @@ UniversalMachOFileContainsArchAndUUID
if (arch)
{
ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
- if (fat_arch != *arch)
+ if (!fat_arch.IsExactMatch(*arch))
continue;
}
@@ -182,7 +177,7 @@ UniversalMachOFileContainsArchAndUUID
DataExtractor arch_data;
DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
arch_data.SetData(data_buffer_sp);
- uint32_t arch_data_offset = 0;
+ lldb::offset_t arch_data_offset = 0;
uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
switch (arch_magic)
@@ -215,7 +210,7 @@ FileAtPathContainsArchAndUUID
{
data.SetData(data_buffer_sp);
- uint32_t data_offset = 0;
+ lldb::offset_t data_offset = 0;
uint32_t magic = data.GetU32(&data_offset);
switch (magic)
@@ -239,12 +234,10 @@ FileAtPathContainsArchAndUUID
return false;
}
-static FileSpec
-LocateDSYMMachFileInDSYMBundle
-(
- const FileSpec& dsym_bundle_fspec,
- const lldb_private::UUID *uuid,
- const ArchSpec *arch)
+FileSpec
+Symbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
+ const lldb_private::UUID *uuid,
+ const ArchSpec *arch)
{
char path[PATH_MAX];
@@ -352,11 +345,11 @@ LocateMacOSXFilesUsingDebugSymbols
{
if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
{
- out_dsym_fspec->SetFile(path, false);
+ out_dsym_fspec->SetFile(path, path[0] == '~');
if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
{
- *out_dsym_fspec = LocateDSYMMachFileInDSYMBundle (*out_dsym_fspec, uuid, arch);
+ *out_dsym_fspec = Symbols::FindSymbolFileInBundle (*out_dsym_fspec, uuid, arch);
if (*out_dsym_fspec)
++items_found;
}
@@ -371,10 +364,8 @@ LocateMacOSXFilesUsingDebugSymbols
CFDictionaryRef uuid_dict = NULL;
if (dict.get())
{
- char uuid_cstr_buf[64];
- const char *uuid_cstr = uuid->GetAsCString (uuid_cstr_buf, sizeof(uuid_cstr_buf));
- CFCString uuid_cfstr (uuid_cstr);
- CFDictionaryRef uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
+ CFCString uuid_cfstr (uuid->GetAsString().c_str());
+ uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
if (uuid_dict)
{
@@ -579,3 +570,232 @@ Symbols::LocateExecutableSymbolFile (con
}
return symbol_fspec;
}
+
+
+static bool
+GetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
+{
+ bool success = false;
+ if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ())
+ {
+ std::string str;
+ CFStringRef cf_str;
+
+ cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable"));
+ if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
+ {
+ if (CFCString::FileSystemRepresentation(cf_str, str))
+ module_spec.GetFileSpec().SetFile (str.c_str(), true);
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath"));
+ if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
+ {
+ if (CFCString::FileSystemRepresentation(cf_str, str))
+ {
+ module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true);
+ success = true;
+ }
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture"));
+ if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
+ {
+ if (CFCString::FileSystemRepresentation(cf_str, str))
+ module_spec.GetArchitecture().SetTriple(str.c_str());
+ }
+
+ std::string DBGBuildSourcePath;
+ std::string DBGSourcePath;
+
+ cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath"));
+ if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
+ {
+ CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
+ }
+
+ cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePath"));
+ if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
+ {
+ CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
+ }
+
+ if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty())
+ {
+ module_spec.GetSourceMappingList().Append (ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true);
+ }
+ }
+ return success;
+}
+
+
+bool
+Symbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
+{
+ bool success = false;
+ const UUID *uuid_ptr = module_spec.GetUUIDPtr();
+ const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
+
+ // It's expensive to check for the DBGShellCommands defaults setting, only do it once per
+ // lldb run and cache the result.
+ static bool g_have_checked_for_dbgshell_command = false;
+ static const char *g_dbgshell_command = NULL;
+ if (g_have_checked_for_dbgshell_command == false)
+ {
+ g_have_checked_for_dbgshell_command = true;
+ CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols"));
+ if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID())
+ {
+ char cstr_buf[PATH_MAX];
+ if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8))
+ {
+ g_dbgshell_command = strdup (cstr_buf); // this malloc'ed memory will never be freed
+ }
+ }
+ if (defaults_setting)
+ {
+ CFRelease (defaults_setting);
+ }
+ }
+
+ // When g_dbgshell_command is NULL, the user has not enabled the use of an external program
+ // to find the symbols, don't run it for them.
+ if (force_lookup == false && g_dbgshell_command == NULL)
+ {
+ return false;
+ }
+
+ if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists()))
+ {
+ static bool g_located_dsym_for_uuid_exe = false;
+ static bool g_dsym_for_uuid_exe_exists = false;
+ static char g_dsym_for_uuid_exe_path[PATH_MAX];
+ if (!g_located_dsym_for_uuid_exe)
+ {
+ g_located_dsym_for_uuid_exe = true;
+ const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
+ FileSpec dsym_for_uuid_exe_spec;
+ if (dsym_for_uuid_exe_path_cstr)
+ {
+ dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
+ g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ }
+
+ if (!g_dsym_for_uuid_exe_exists)
+ {
+ dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
+ g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ if (!g_dsym_for_uuid_exe_exists)
+ {
+ long bufsize;
+ if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1)
+ {
+ char buffer[bufsize];
+ struct passwd pwd;
+ struct passwd *tilde_rc = NULL;
+ // we are a library so we need to use the reentrant version of getpwnam()
+ if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0
+ && tilde_rc
+ && tilde_rc->pw_dir)
+ {
+ std::string dsymforuuid_path(tilde_rc->pw_dir);
+ dsymforuuid_path += "/bin/dsymForUUID";
+ dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false);
+ g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ }
+ }
+ }
+ }
+ if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL)
+ {
+ dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true);
+ g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ }
+
+ if (g_dsym_for_uuid_exe_exists)
+ dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path));
+ }
+ if (g_dsym_for_uuid_exe_exists)
+ {
+ std::string uuid_str;
+ char file_path[PATH_MAX];
+ file_path[0] = '\0';
+
+ if (uuid_ptr)
+ uuid_str = uuid_ptr->GetAsString();
+
+ if (file_spec_ptr)
+ file_spec_ptr->GetPath(file_path, sizeof(file_path));
+
+ StreamString command;
+ if (!uuid_str.empty())
+ command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_str.c_str());
+ else if (file_path && file_path[0])
+ command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path);
+
+ if (!command.GetString().empty())
+ {
+ int exit_status = -1;
+ int signo = -1;
+ std::string command_output;
+ Error error = Host::RunShellCommand (command.GetData(),
+ NULL, // current working directory
+ &exit_status, // Exit status
+ &signo, // Signal int *
+ &command_output, // Command output
+ 30, // Large timeout to allow for long dsym download times
+ NULL); // Don't run in a shell (we don't need shell expansion)
+ if (error.Success() && exit_status == 0 && !command_output.empty())
+ {
+ CFCData data (CFDataCreateWithBytesNoCopy (NULL,
+ (const UInt8 *)command_output.data(),
+ command_output.size(),
+ kCFAllocatorNull));
+
+ CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL));
+
+ if (plist.get() && CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ())
+ {
+ if (!uuid_str.empty())
+ {
+ CFCString uuid_cfstr(uuid_str.c_str());
+ CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get());
+ success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec);
+ }
+ else
+ {
+ const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
+ if (num_values > 0)
+ {
+ std::vector<CFStringRef> keys (num_values, NULL);
+ std::vector<CFDictionaryRef> values (num_values, NULL);
+ ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]);
+ if (num_values == 1)
+ {
+ return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec);
+ }
+ else
+ {
+ for (CFIndex i=0; i<num_values; ++i)
+ {
+ ModuleSpec curr_module_spec;
+ if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec))
+ {
+ if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture()))
+ {
+ module_spec = curr_module_spec;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return success;
+}
+
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.cpp Thu Jun 6 19:06:43 2013
@@ -432,6 +432,44 @@ CFCMutableDictionary::SetValueUInt64(CFS
}
bool
+CFCMutableDictionary::AddValueDouble(CFStringRef key, double value, bool can_create)
+{
+ CFMutableDictionaryRef dict = Dictionary(can_create);
+ if (dict != NULL)
+ {
+ // The number may appear negative if the MSBit is set in "value". Due to a limitation of
+ // CFNumber, there isn't a way to have it show up otherwise as of this writing.
+ CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value));
+ if (cf_number.get())
+ {
+ // Let the dictionary own the CFNumber
+ ::CFDictionaryAddValue (dict, key, cf_number.get());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+CFCMutableDictionary::SetValueDouble(CFStringRef key, double value, bool can_create)
+{
+ CFMutableDictionaryRef dict = Dictionary(can_create);
+ if (dict != NULL)
+ {
+ // The number may appear negative if the MSBit is set in "value". Due to a limitation of
+ // CFNumber, there isn't a way to have it show up otherwise as of this writing.
+ CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &value));
+ if (cf_number.get())
+ {
+ // Let the dictionary own the CFNumber
+ ::CFDictionarySetValue (dict, key, cf_number.get());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
CFCMutableDictionary::AddValueCString(CFStringRef key, const char *cstr, bool can_create)
{
CFMutableDictionaryRef dict = Dictionary(can_create);
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.h (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/cfcpp/CFCMutableDictionary.h Thu Jun 6 19:06:43 2013
@@ -53,6 +53,8 @@ public:
bool SetValueUInt32(CFStringRef key, uint32_t value, bool can_create = false);
bool AddValueUInt64(CFStringRef key, uint64_t value, bool can_create = false);
bool SetValueUInt64(CFStringRef key, uint64_t value, bool can_create = false);
+ bool AddValueDouble(CFStringRef key, double value, bool can_create = false);
+ bool SetValueDouble(CFStringRef key, double value, bool can_create = false);
bool AddValueCString(CFStringRef key, const char *cstr, bool can_create = false);
bool SetValueCString(CFStringRef key, const char *cstr, bool can_create = false);
void RemoveValue(const void *value);
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist Thu Jun 6 19:06:43 2013
@@ -25,7 +25,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>165</string>
+ <string>300.99.0</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 Apple Inc. All rights reserved.</string>
<key>XPCService</key>
@@ -39,6 +39,8 @@
<string>root</string>
<key>ServiceType</key>
<string>Application</string>
+ <key>JoinExistingSession</key>
+ <true/>
</dict>
</dict>
</plist>
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherXPCService-Info.plist
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherXPCService-Info.plist?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherXPCService-Info.plist (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/LauncherXPCService-Info.plist Thu Jun 6 19:06:43 2013
@@ -25,7 +25,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>165</string>
+ <string>300.99.0</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 Apple Inc. All rights reserved.</string>
<key>XPCService</key>
Modified: lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/main.mm
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/main.mm?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/main.mm (original)
+++ lldb/branches/lldb-platform-work/source/Host/macosx/launcherXPCService/main.mm Thu Jun 6 19:06:43 2013
@@ -16,6 +16,7 @@
#include <spawn.h>
#include <signal.h>
#include <assert.h>
+#include <sys/errno.h>
#include "LauncherXPCService.h"
// Declaration. Returns 0 if successful.
@@ -109,6 +110,31 @@ int get_args(xpc_object_t message, const
return 0;
}
+void _wait_for_child_exit(pid_t childPID)
+{
+ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+ dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, childPID, DISPATCH_PROC_EXIT, queue);
+
+ if (source) {
+ dispatch_source_set_cancel_handler(source, ^{
+ dispatch_release(source);
+ });
+
+ dispatch_source_set_event_handler(source, ^{
+
+ // Either finding the process was successful, or the process disappeared before libdispatch got around to hooking up the source.
+ dispatch_source_cancel(source);
+
+ int status, ret;
+ do {
+ ret = waitpid(childPID, &status, 0);
+ } while (ret < 0 && errno == EINTR);
+
+ });
+ dispatch_resume(source);
+ }
+}
+
static void launcherXPC_peer_event_handler(xpc_connection_t peer, xpc_object_t event)
{
xpc_type_t type = xpc_get_type(event);
@@ -154,6 +180,10 @@ static void launcherXPC_peer_event_handl
if (argvp) free(argvp);
if (envp) free(envp);
+
+ if (errorCode == 0) {
+ _wait_for_child_exit(childPID);
+ }
}
}
}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/Args.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/Args.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/Args.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/Args.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
// C Includes
#include <getopt.h>
#include <cstdlib>
@@ -14,12 +16,17 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Interpreter/Args.h"
-#include "lldb/Core/FormatManager.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+//#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+//#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -91,24 +98,15 @@ Args::~Args ()
void
Args::Dump (Stream *s)
{
-// int argc = GetArgumentCount();
-//
-// arg_sstr_collection::const_iterator pos, begin = m_args.begin(), end = m_args.end();
-// for (pos = m_args.begin(); pos != end; ++pos)
-// {
-// s->Indent();
-// s->Printf("args[%zu]=%s\n", std::distance(begin, pos), pos->c_str());
-// }
-// s->EOL();
- const int argc = m_argv.size();
- for (int i=0; i<argc; ++i)
+ const size_t argc = m_argv.size();
+ for (size_t i=0; i<argc; ++i)
{
s->Indent();
const char *arg_cstr = m_argv[i];
if (arg_cstr)
- s->Printf("argv[%i]=\"%s\"\n", i, arg_cstr);
+ s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
else
- s->Printf("argv[%i]=NULL\n", i);
+ s->Printf("argv[%zi]=NULL\n", i);
}
s->EOL();
}
@@ -117,8 +115,8 @@ bool
Args::GetCommandString (std::string &command) const
{
command.clear();
- int argc = GetArgumentCount();
- for (int i=0; i<argc; ++i)
+ const size_t argc = GetArgumentCount();
+ for (size_t i=0; i<argc; ++i)
{
if (i > 0)
command += ' ';
@@ -131,7 +129,7 @@ bool
Args::GetQuotedCommandString (std::string &command) const
{
command.clear ();
- size_t argc = GetArgumentCount ();
+ const size_t argc = GetArgumentCount();
for (size_t i = 0; i < argc; ++i)
{
if (i > 0)
@@ -573,7 +571,7 @@ Args::DeleteArgumentAtIndex (size_t idx)
}
void
-Args::SetArguments (int argc, const char **argv)
+Args::SetArguments (size_t argc, const char **argv)
{
// m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
// no need to clear it here.
@@ -634,13 +632,16 @@ Args::ParseOptions (Options &options)
{
if (long_options[i].flag == NULL)
{
- sstr << (char)long_options[i].val;
- switch (long_options[i].has_arg)
+ if (isprint8(long_options[i].val))
{
- default:
- case no_argument: break;
- case required_argument: sstr << ':'; break;
- case optional_argument: sstr << "::"; break;
+ sstr << (char)long_options[i].val;
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument: break;
+ case required_argument: sstr << ':'; break;
+ case optional_argument: sstr << "::"; break;
+ }
}
}
}
@@ -654,8 +655,11 @@ Args::ParseOptions (Options &options)
while (1)
{
int long_options_index = -1;
- val = ::getopt_long(GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
- &long_options_index);
+ val = ::getopt_long_only(GetArgumentCount(),
+ GetArgumentVector(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
if (val == -1)
break;
@@ -719,11 +723,12 @@ Args::StringToSInt32 (const char *s, int
if (s && s[0])
{
char *end = NULL;
- int32_t uval = ::strtol (s, &end, base);
+ const long sval = ::strtol (s, &end, base);
if (*end == '\0')
{
- if (success_ptr) *success_ptr = true;
- return uval; // All characters were used, return the result
+ if (success_ptr)
+ *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
+ return (int32_t)sval; // All characters were used, return the result
}
}
if (success_ptr) *success_ptr = false;
@@ -736,11 +741,12 @@ Args::StringToUInt32 (const char *s, uin
if (s && s[0])
{
char *end = NULL;
- uint32_t uval = ::strtoul (s, &end, base);
+ const unsigned long uval = ::strtoul (s, &end, base);
if (*end == '\0')
{
- if (success_ptr) *success_ptr = true;
- return uval; // All characters were used, return the result
+ if (success_ptr)
+ *success_ptr = (uval <= UINT32_MAX);
+ return (uint32_t)uval; // All characters were used, return the result
}
}
if (success_ptr) *success_ptr = false;
@@ -783,29 +789,150 @@ Args::StringToUInt64 (const char *s, uin
}
lldb::addr_t
-Args::StringToAddress (const char *s, lldb::addr_t fail_value, bool *success_ptr)
+Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
{
+ bool error_set = false;
if (s && s[0])
{
char *end = NULL;
lldb::addr_t addr = ::strtoull (s, &end, 0);
if (*end == '\0')
{
- if (success_ptr) *success_ptr = true;
+ if (error_ptr)
+ error_ptr->Clear();
return addr; // All characters were used, return the result
}
// Try base 16 with no prefix...
addr = ::strtoull (s, &end, 16);
if (*end == '\0')
{
- if (success_ptr) *success_ptr = true;
+ if (error_ptr)
+ error_ptr->Clear();
return addr; // All characters were used, return the result
}
+
+ if (exe_ctx)
+ {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ {
+ lldb::ValueObjectSP valobj_sp;
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(false);
+ options.SetRunOthers(true);
+
+ ExecutionResults expr_result = target->EvaluateExpression(s,
+ exe_ctx->GetFramePtr(),
+ valobj_sp,
+ options);
+
+ bool success = false;
+ if (expr_result == eExecutionCompleted)
+ {
+ // Get the address to watch.
+ addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
+ if (success)
+ {
+ if (error_ptr)
+ error_ptr->Clear();
+ return addr;
+ }
+ else
+ {
+ if (error_ptr)
+ {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString());
+ }
+ }
+
+ }
+ else
+ {
+ // Since the compiler can't handle things like "main + 12" we should
+ // try to do this for now. The compliler doesn't like adding offsets
+ // to function pointer types.
+ static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
+ RegularExpression::Match regex_match(3);
+ if (g_symbol_plus_offset_regex.Execute(s, ®ex_match))
+ {
+ uint64_t offset = 0;
+ bool add = true;
+ std::string name;
+ std::string str;
+ if (regex_match.GetMatchAtIndex(s, 1, name))
+ {
+ if (regex_match.GetMatchAtIndex(s, 2, str))
+ {
+ add = str[0] == '+';
+
+ if (regex_match.GetMatchAtIndex(s, 3, str))
+ {
+ offset = Args::StringToUInt64(str.c_str(), 0, 0, &success);
+
+ if (success)
+ {
+ Error error;
+ addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ if (add)
+ return addr + offset;
+ else
+ return addr - offset;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (error_ptr)
+ {
+ error_set = true;
+ error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
+ }
+ }
+ }
+ }
+ }
+ if (error_ptr)
+ {
+ if (!error_set)
+ error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
}
- if (success_ptr) *success_ptr = false;
return fail_value;
}
+const char *
+Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
+{
+ static const char *k_white_space = " \t\v";
+ if (!s.empty())
+ {
+ if (leading)
+ {
+ size_t pos = s.find_first_not_of (k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos > 0)
+ s.erase(0, pos);
+ }
+
+ if (trailing)
+ {
+ size_t rpos = s.find_last_not_of(k_white_space);
+ if (rpos != std::string::npos && rpos + 1 < s.size())
+ s.erase(rpos + 1);
+ }
+ }
+ if (return_null_if_empty && s.empty())
+ return NULL;
+ return s.c_str();
+}
+
bool
Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
{
@@ -844,8 +971,7 @@ Args::StringToVersion (const char *s, ui
if (s && s[0])
{
char *pos = NULL;
- uint32_t uval32;
- uval32 = ::strtoul (s, &pos, 0);
+ unsigned long uval32 = ::strtoul (s, &pos, 0);
if (pos == s)
return s;
major = uval32;
@@ -895,7 +1021,7 @@ Args::GetShellSafeArgument (const char *
}
-int32_t
+int64_t
Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
{
if (enum_values)
@@ -955,7 +1081,7 @@ Args::StringToFormat
(
const char *s,
lldb::Format &format,
- uint32_t *byte_size_ptr
+ size_t *byte_size_ptr
)
{
format = eFormatInvalid;
@@ -1007,6 +1133,60 @@ Args::StringToFormat
return error;
}
+lldb::Encoding
+Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
+{
+ if (s && s[0])
+ {
+ if (strcmp(s, "uint") == 0)
+ return eEncodingUint;
+ else if (strcmp(s, "sint") == 0)
+ return eEncodingSint;
+ else if (strcmp(s, "ieee754") == 0)
+ return eEncodingIEEE754;
+ else if (strcmp(s, "vector") == 0)
+ return eEncodingVector;
+ }
+ return fail_value;
+}
+
+uint32_t
+Args::StringToGenericRegister (const char *s)
+{
+ if (s && s[0])
+ {
+ if (strcmp(s, "pc") == 0)
+ return LLDB_REGNUM_GENERIC_PC;
+ else if (strcmp(s, "sp") == 0)
+ return LLDB_REGNUM_GENERIC_SP;
+ else if (strcmp(s, "fp") == 0)
+ return LLDB_REGNUM_GENERIC_FP;
+ else if (strcmp(s, "ra") == 0)
+ return LLDB_REGNUM_GENERIC_RA;
+ else if (strcmp(s, "flags") == 0)
+ return LLDB_REGNUM_GENERIC_FLAGS;
+ else if (strncmp(s, "arg", 3) == 0)
+ {
+ if (s[3] && s[4] == '\0')
+ {
+ switch (s[3])
+ {
+ case '1': return LLDB_REGNUM_GENERIC_ARG1;
+ case '2': return LLDB_REGNUM_GENERIC_ARG2;
+ case '3': return LLDB_REGNUM_GENERIC_ARG3;
+ case '4': return LLDB_REGNUM_GENERIC_ARG4;
+ case '5': return LLDB_REGNUM_GENERIC_ARG5;
+ case '6': return LLDB_REGNUM_GENERIC_ARG6;
+ case '7': return LLDB_REGNUM_GENERIC_ARG7;
+ case '8': return LLDB_REGNUM_GENERIC_ARG8;
+ }
+ }
+ }
+ }
+ return LLDB_INVALID_REGNUM;
+}
+
+
void
Args::LongestCommonPrefix (std::string &common_prefix)
{
@@ -1047,7 +1227,7 @@ Args::FindArgumentIndexForOption (struct
{
char short_buffer[3];
char long_buffer[255];
- ::snprintf (short_buffer, sizeof (short_buffer), "-%c", (char) long_options[long_options_index].val);
+ ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
size_t end = GetArgumentCount ();
size_t idx = 0;
@@ -1134,8 +1314,11 @@ Args::ParseAliasOptions (Options &option
while (1)
{
int long_options_index = -1;
- val = ::getopt_long (GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
- &long_options_index);
+ val = ::getopt_long_only (GetArgumentCount(),
+ GetArgumentVector(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
if (val == -1)
break;
@@ -1171,7 +1354,7 @@ Args::ParseAliasOptions (Options &option
if (long_options_index >= 0)
{
StreamString option_str;
- option_str.Printf ("-%c", (char) val);
+ option_str.Printf ("-%c", val);
switch (long_options[long_options_index].has_arg)
{
@@ -1211,16 +1394,14 @@ Args::ParseAliasOptions (Options &option
}
break;
default:
- result.AppendErrorWithFormat
- ("error with options table; invalid value in has_arg field for option '%c'.\n",
- (char) val);
+ result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
result.SetStatus (eReturnStatusFailed);
break;
}
}
else
{
- result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", (char) val);
+ result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
result.SetStatus (eReturnStatusFailed);
}
@@ -1314,8 +1495,8 @@ Args::ParseArgsForCompletion
int val;
const OptionDefinition *opt_defs = options.GetDefinitions();
- // Fooey... getopt_long permutes the GetArgumentVector to move the options to the front.
- // So we have to build another Arg and pass that to getopt_long so it doesn't
+ // Fooey... getopt_long_only permutes the GetArgumentVector to move the options to the front.
+ // So we have to build another Arg and pass that to getopt_long_only so it doesn't
// change the one we have.
std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
@@ -1326,14 +1507,13 @@ Args::ParseArgsForCompletion
while (1)
{
bool missing_argument = false;
- int parse_start = optind;
int long_options_index = -1;
- val = ::getopt_long (dummy_vec.size() - 1,
- (char *const *) &dummy_vec.front(),
- sstr.GetData(),
- long_options,
- &long_options_index);
+ val = ::getopt_long_only (dummy_vec.size() - 1,
+ (char *const *) &dummy_vec.front(),
+ sstr.GetData(),
+ long_options,
+ &long_options_index);
if (val == -1)
{
@@ -1347,7 +1527,7 @@ Args::ParseArgsForCompletion
// Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
// user might want to complete options by long name. I make this work by checking whether the
// cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
- // I let it pass to getopt_long which will terminate the option parsing.
+ // I let it pass to getopt_long_only which will terminate the option parsing.
// Note, in either case we continue parsing the line so we can figure out what other options
// were passed. This will be useful when we come to restricting completions based on what other
// options we've seen on the line.
@@ -1420,7 +1600,7 @@ Args::ParseArgsForCompletion
switch (long_options[long_options_index].has_arg)
{
case no_argument:
- option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, 0));
+ option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, 0));
break;
case required_argument:
if (optarg != NULL)
@@ -1463,7 +1643,7 @@ Args::ParseArgsForCompletion
}
// Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
- // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long just ignores
+ // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long_only just ignores
// an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
@@ -1474,3 +1654,136 @@ Args::ParseArgsForCompletion
}
}
+
+void
+Args::EncodeEscapeSequences (const char *src, std::string &dst)
+{
+ dst.clear();
+ if (src)
+ {
+ for (const char *p = src; *p != '\0'; ++p)
+ {
+ size_t non_special_chars = ::strcspn (p, "\\");
+ if (non_special_chars > 0)
+ {
+ dst.append(p, non_special_chars);
+ p += non_special_chars;
+ if (*p == '\0')
+ break;
+ }
+
+ if (*p == '\\')
+ {
+ ++p; // skip the slash
+ switch (*p)
+ {
+ case 'a' : dst.append(1, '\a'); break;
+ case 'b' : dst.append(1, '\b'); break;
+ case 'f' : dst.append(1, '\f'); break;
+ case 'n' : dst.append(1, '\n'); break;
+ case 'r' : dst.append(1, '\r'); break;
+ case 't' : dst.append(1, '\t'); break;
+ case 'v' : dst.append(1, '\v'); break;
+ case '\\': dst.append(1, '\\'); break;
+ case '\'': dst.append(1, '\''); break;
+ case '"' : dst.append(1, '"'); break;
+ case '0' :
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char,
+ // up to 3 octal digits, and a terminating NULL.
+ char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
+
+ int i;
+ for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
+ oct_str[i] = p[i];
+
+ // We don't want to consume the last octal character since
+ // the main for loop will do this for us, so we advance p by
+ // one less than i (even if i is zero)
+ p += i - 1;
+ unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
+ if (octal_value <= UINT8_MAX)
+ {
+ dst.append(1, (char)octal_value);
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(p[1]))
+ {
+ ++p; // Skip the 'x'
+
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = { *p, '\0', '\0' };
+ if (isxdigit(p[1]))
+ {
+ ++p; // Skip the first of the two hex chars
+ hex_str[1] = *p;
+ }
+
+ unsigned long hex_value = strtoul (hex_str, NULL, 16);
+ if (hex_value <= UINT8_MAX)
+ dst.append (1, (char)hex_value);
+ }
+ else
+ {
+ dst.append(1, 'x');
+ }
+ break;
+
+ default:
+ // Just desensitize any other character by just printing what
+ // came after the '\'
+ dst.append(1, *p);
+ break;
+
+ }
+ }
+ }
+ }
+}
+
+
+void
+Args::ExpandEscapedCharacters (const char *src, std::string &dst)
+{
+ dst.clear();
+ if (src)
+ {
+ for (const char *p = src; *p != '\0'; ++p)
+ {
+ if (isprint8(*p))
+ dst.append(1, *p);
+ else
+ {
+ switch (*p)
+ {
+ case '\a': dst.append("\\a"); break;
+ case '\b': dst.append("\\b"); break;
+ case '\f': dst.append("\\f"); break;
+ case '\n': dst.append("\\n"); break;
+ case '\r': dst.append("\\r"); break;
+ case '\t': dst.append("\\t"); break;
+ case '\v': dst.append("\\v"); break;
+ case '\'': dst.append("\\'"); break;
+ case '"': dst.append("\\\""); break;
+ case '\\': dst.append("\\\\"); break;
+ default:
+ {
+ // Just encode as octal
+ dst.append("\\0");
+ char octal_str[32];
+ snprintf(octal_str, sizeof(octal_str), "%o", *p);
+ dst.append(octal_str);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandInterpreter.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandInterpreter.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandInterpreter.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include <string>
#include <vector>
@@ -26,6 +28,7 @@
#include "../Commands/CommandObjectLog.h"
#include "../Commands/CommandObjectMemory.h"
#include "../Commands/CommandObjectPlatform.h"
+#include "../Commands/CommandObjectPlugin.h"
#include "../Commands/CommandObjectProcess.h"
#include "../Commands/CommandObjectQuit.h"
#include "../Commands/CommandObjectRegister.h"
@@ -39,26 +42,48 @@
#include "../Commands/CommandObjectVersion.h"
#include "../Commands/CommandObjectWatchpoint.h"
-#include "lldb/Interpreter/Args.h"
-#include "lldb/Interpreter/Options.h"
+
#include "lldb/Core/Debugger.h"
#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/Timer.h"
+
#include "lldb/Host/Host.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/TargetList.h"
-#include "lldb/Utility/CleanUp.h"
-#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/ScriptInterpreterNone.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/TargetList.h"
+
+#include "lldb/Utility/CleanUp.h"
+
using namespace lldb;
using namespace lldb_private;
+
+static PropertyDefinition
+g_properties[] =
+{
+ { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
+ { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
+ { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
+};
+
+enum
+{
+ ePropertyExpandRegexAliases = 0,
+ ePropertyPromptOnQuit = 1
+};
+
ConstString &
CommandInterpreter::GetStaticBroadcasterClass ()
{
@@ -73,6 +98,7 @@ CommandInterpreter::CommandInterpreter
bool synchronous_execution
) :
Broadcaster (&debugger, "lldb.command-interpreter"),
+ Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
m_debugger (debugger),
m_synchronous_execution (synchronous_execution),
m_skip_lldbinit_files (false),
@@ -84,18 +110,26 @@ CommandInterpreter::CommandInterpreter
m_truncation_warning(eNoTruncation),
m_command_source_depth (0)
{
- const char *dbg_name = debugger.GetInstanceName().AsCString();
- std::string lang_name = ScriptInterpreter::LanguageToString (script_language);
- StreamString var_name;
- var_name.Printf ("[%s].script-lang", dbg_name);
- debugger.GetSettingsController()->SetVariable (var_name.GetData(), lang_name.c_str(),
- eVarSetOperationAssign, false,
- m_debugger.GetInstanceName().AsCString());
+ debugger.SetScriptLanguage (script_language);
SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
- SetEventName (eBroadcastBitQuitCommandReceived, "quit");
-
+ SetEventName (eBroadcastBitQuitCommandReceived, "quit");
CheckInWithManager ();
+ m_collection_sp->Initialize (g_properties);
+}
+
+bool
+CommandInterpreter::GetExpandRegexAliases () const
+{
+ const uint32_t idx = ePropertyExpandRegexAliases;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+}
+
+bool
+CommandInterpreter::GetPromptOnQuit () const
+{
+ const uint32_t idx = ePropertyPromptOnQuit;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
}
void
@@ -115,12 +149,18 @@ CommandInterpreter::Initialize ()
AddAlias ("exit", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact ("process attach", false);
+ cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
if (cmd_obj_sp)
{
AddAlias ("attach", cmd_obj_sp);
}
+ cmd_obj_sp = GetCommandSPExact ("process detach",false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("detach", cmd_obj_sp);
+ }
+
cmd_obj_sp = GetCommandSPExact ("process continue", false);
if (cmd_obj_sp)
{
@@ -132,9 +172,9 @@ CommandInterpreter::Initialize ()
if (cmd_obj_sp)
AddAlias ("b", cmd_obj_sp);
- cmd_obj_sp = GetCommandSPExact ("thread backtrace", false);
+ cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
if (cmd_obj_sp)
- AddAlias ("bt", cmd_obj_sp);
+ AddAlias ("tbreak", cmd_obj_sp);
cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
if (cmd_obj_sp)
@@ -176,13 +216,25 @@ CommandInterpreter::Initialize ()
AddAlias ("f", cmd_obj_sp);
}
- cmd_obj_sp = GetCommandSPExact ("source list", false);
+ cmd_obj_sp = GetCommandSPExact ("thread select", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("t", cmd_obj_sp);
+ }
+
+ cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
if (cmd_obj_sp)
{
AddAlias ("l", cmd_obj_sp);
AddAlias ("list", cmd_obj_sp);
}
+ cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
+ if (cmd_obj_sp)
+ {
+ AddAlias ("env", cmd_obj_sp);
+ }
+
cmd_obj_sp = GetCommandSPExact ("memory read", false);
if (cmd_obj_sp)
AddAlias ("x", cmd_obj_sp);
@@ -213,6 +265,10 @@ CommandInterpreter::Initialize ()
if (cmd_obj_sp)
AddAlias ("undisplay", cmd_obj_sp);
+ cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
+ if (cmd_obj_sp)
+ AddAlias ("bt", cmd_obj_sp);
+
cmd_obj_sp = GetCommandSPExact ("target create", false);
if (cmd_obj_sp)
AddAlias ("file", cmd_obj_sp);
@@ -226,9 +282,7 @@ CommandInterpreter::Initialize ()
cmd_obj_sp = GetCommandSPExact ("expression", false);
if (cmd_obj_sp)
- {
- AddAlias ("expr", cmd_obj_sp);
-
+ {
ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
AddAlias ("p", cmd_obj_sp);
AddAlias ("print", cmd_obj_sp);
@@ -238,14 +292,16 @@ CommandInterpreter::Initialize ()
AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
alias_arguments_vector_sp.reset (new OptionArgVector);
- ProcessAliasOptionsArgs (cmd_obj_sp, "-o --", alias_arguments_vector_sp);
+ ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
AddAlias ("po", cmd_obj_sp);
AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
}
cmd_obj_sp = GetCommandSPExact ("process kill", false);
if (cmd_obj_sp)
+ {
AddAlias ("kill", cmd_obj_sp);
+ }
cmd_obj_sp = GetCommandSPExact ("process launch", false);
if (cmd_obj_sp)
@@ -273,8 +329,8 @@ CommandInterpreter::Initialize ()
{
alias_arguments_vector_sp.reset (new OptionArgVector);
ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
- AddAlias ("rb", cmd_obj_sp);
- AddOrReplaceAliasOptions("rb", alias_arguments_vector_sp);
+ AddAlias ("rbreak", cmd_obj_sp);
+ AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
}
}
@@ -299,37 +355,19 @@ CommandInterpreter::LoadCommandDictionar
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
- // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
- //
- // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref)
- // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use
- // the cross-referencing stuff) are created!!!
- //
- // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT ***
-
-
- // Command objects that inherit from CommandObjectCrossref must be created before other command objects
- // are created. This is so that when another command is created that needs to go into a crossref object,
- // the crossref object exists and is ready to take the cross reference. Put the cross referencing command
- // objects into the CommandDictionary now, so they are ready for use when the other commands get created.
-
- // Non-CommandObjectCrossref commands can now be created.
-
lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this));
m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
- //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall (*this));
m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
-// m_command_dict["file"] = CommandObjectSP (new CommandObjectFile (*this));
m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this));
- /// m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (*this));
m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this));
m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this));
m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this));
+ m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this));
m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this));
m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this));
@@ -342,27 +380,94 @@ CommandInterpreter::LoadCommandDictionar
m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
- std::auto_ptr<CommandObjectRegexCommand>
+ const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
+ {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
+ {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
+ {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
+ {"^(-.*)$", "breakpoint set %1"},
+ {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
+ {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
+ {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
+
+ size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
+
+ std::unique_ptr<CommandObjectRegexCommand>
break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
"_regexp-break",
- "Set a breakpoint using a regular expression to specify the location.",
- "_regexp-break [<filename>:<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
+ "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
+ "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
+ 2,
+ CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion));
+
if (break_regex_cmd_ap.get())
{
- if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
- break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
- break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
- break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full") &&
- break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
- break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'") &&
- break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++)
+ {
+ success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
+ if (!success)
+ break;
+ }
+ success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success)
{
CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
}
}
- std::auto_ptr<CommandObjectRegexCommand>
+ std::unique_ptr<CommandObjectRegexCommand>
+ tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-tbreak",
+ "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
+ "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
+ 2,
+ CommandCompletions::eSymbolCompletion |
+ CommandCompletions::eSourceFileCompletion));
+
+ if (tbreak_regex_cmd_ap.get())
+ {
+ bool success = true;
+ for (size_t i = 0; i < num_regexes; i++)
+ {
+ // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
+ char buffer[1024];
+ int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
+ assert (num_printed < 1024);
+ success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
+ if (!success)
+ break;
+ }
+ success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
+
+ if (success)
+ {
+ CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
+ m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-attach",
+ "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
+ "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
+ 2));
+ if (attach_regex_cmd_ap.get())
+ {
+ if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
+ attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
+ attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
+ attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
+ {
+ CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
+ m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
"_regexp-down",
"Go down \"n\" frames in the stack (1 frame by default).",
@@ -377,7 +482,7 @@ CommandInterpreter::LoadCommandDictionar
}
}
- std::auto_ptr<CommandObjectRegexCommand>
+ std::unique_ptr<CommandObjectRegexCommand>
up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
"_regexp-up",
"Go up \"n\" frames in the stack (1 frame by default).",
@@ -392,11 +497,11 @@ CommandInterpreter::LoadCommandDictionar
}
}
- std::auto_ptr<CommandObjectRegexCommand>
+ std::unique_ptr<CommandObjectRegexCommand>
display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-display",
- "Add an expression evaluation stop-hook.",
- "_regexp-display expression", 2));
+ "_regexp-display",
+ "Add an expression evaluation stop-hook.",
+ "_regexp-display expression", 2));
if (display_regex_cmd_ap.get())
{
if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
@@ -406,11 +511,11 @@ CommandInterpreter::LoadCommandDictionar
}
}
- std::auto_ptr<CommandObjectRegexCommand>
+ std::unique_ptr<CommandObjectRegexCommand>
undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "_regexp-undisplay",
- "Remove an expression evaluation stop-hook.",
- "_regexp-undisplay stop-hook-number", 2));
+ "_regexp-undisplay",
+ "Remove an expression evaluation stop-hook.",
+ "_regexp-undisplay stop-hook-number", 2));
if (undisplay_regex_cmd_ap.get())
{
if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
@@ -420,6 +525,93 @@ CommandInterpreter::LoadCommandDictionar
}
}
+ std::unique_ptr<CommandObjectRegexCommand>
+ connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
+ "gdb-remote",
+ "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.",
+ "gdb-remote [<hostname>:]<portnum>", 2));
+ if (connect_gdb_remote_cmd_ap.get())
+ {
+ if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
+ connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
+ {
+ CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
+ "kdp-remote",
+ "Connect to a remote KDP server. udp port 41139 is the default port number.",
+ "kdp-remote <hostname>[:<portnum>]", 2));
+ if (connect_kdp_remote_cmd_ap.get())
+ {
+ if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
+ connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
+ {
+ CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-bt",
+ "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.",
+ "bt [<digit>|all]", 2));
+ if (bt_regex_cmd_ap.get())
+ {
+ // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
+ // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
+ // so now "bt 3" is the preferred form, in line with gdb.
+ if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
+ bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
+ bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
+ {
+ CommandObjectSP command_sp(bt_regex_cmd_ap.release());
+ m_command_dict[command_sp->GetCommandName ()] = command_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-list",
+ "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
+ "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]",
+ 2,
+ CommandCompletions::eSourceFileCompletion));
+ if (list_regex_cmd_ap.get())
+ {
+ if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
+ list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
+ list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
+ list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
+ list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
+ {
+ CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
+ m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
+ }
+ }
+
+ std::unique_ptr<CommandObjectRegexCommand>
+ env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
+ "_regexp-env",
+ "Implements a shortcut to viewing and setting environment variables.",
+ "_regexp-env\n_regexp-env FOO=BAR", 2));
+ if (env_regex_cmd_ap.get())
+ {
+ if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
+ env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
+ {
+ CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
+ m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
+ }
+ }
+
}
int
@@ -440,7 +632,7 @@ CommandObjectSP
CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
{
CommandObject::CommandMap::iterator pos;
- CommandObjectSP ret_val;
+ CommandObjectSP command_sp;
std::string cmd(cmd_cstr);
@@ -448,24 +640,24 @@ CommandInterpreter::GetCommandSP (const
{
pos = m_command_dict.find(cmd);
if (pos != m_command_dict.end())
- ret_val = pos->second;
+ command_sp = pos->second;
}
if (include_aliases && HasAliases())
{
pos = m_alias_dict.find(cmd);
if (pos != m_alias_dict.end())
- ret_val = pos->second;
+ command_sp = pos->second;
}
if (HasUserCommands())
{
pos = m_user_dict.find(cmd);
if (pos != m_user_dict.end())
- ret_val = pos->second;
+ command_sp = pos->second;
}
- if (!exact && !ret_val)
+ if (!exact && !command_sp)
{
// We will only get into here if we didn't find any exact matches.
@@ -535,13 +727,13 @@ CommandInterpreter::GetCommandSP (const
return user_match_sp;
}
}
- else if (matches && ret_val)
+ else if (matches && command_sp)
{
matches->AppendString (cmd_cstr);
}
- return ret_val;
+ return command_sp;
}
bool
@@ -550,11 +742,11 @@ CommandInterpreter::AddCommand (const ch
if (name && name[0])
{
std::string name_sstr(name);
- if (!can_replace)
- {
- if (m_command_dict.find (name_sstr) != m_command_dict.end())
- return false;
- }
+ bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
+ if (found && !can_replace)
+ return false;
+ if (found && m_command_dict[name_sstr]->IsRemovable() == false)
+ return false;
m_command_dict[name_sstr] = cmd_sp;
return true;
}
@@ -573,11 +765,21 @@ CommandInterpreter::AddUserCommand (std:
// do not allow replacement of internal commands
if (CommandExists(name_cstr))
- return false;
+ {
+ if (can_replace == false)
+ return false;
+ if (m_command_dict[name]->IsRemovable() == false)
+ return false;
+ }
+
+ if (UserCommandExists(name_cstr))
+ {
+ if (can_replace == false)
+ return false;
+ if (m_user_dict[name]->IsRemovable() == false)
+ return false;
+ }
- if (can_replace == false && UserCommandExists(name_cstr))
- return false;
-
m_user_dict[name] = cmd_sp;
return true;
}
@@ -609,8 +811,7 @@ CommandInterpreter::GetCommandSPExact (c
{
if (cmd_obj_sp->IsMultiwordObject())
{
- cmd_obj_sp = ((CommandObjectMultiword *) cmd_obj_sp.get())->GetSubcommandSP
- (cmd_words.GetArgumentAtIndex (j));
+ cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
if (cmd_obj_sp.get() == NULL)
// The sub-command name was invalid. Fail and return the empty 'ret_val'.
return ret_val;
@@ -647,9 +848,14 @@ CommandInterpreter::GetCommandObject (co
command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
}
- // Finally, if there wasn't an exact match among the aliases, look for an inexact match
- // in both the commands and the aliases.
+ // If there wasn't an exact match among the aliases, look for an inexact match
+ // in just the commands.
+
+ if (command_obj == NULL)
+ command_obj = GetCommandSP(cmd_cstr, false, false, matches).get();
+ // Finally, if there wasn't an inexact match among the commands, look for an inexact
+ // match in both the commands and aliases.
if (command_obj == NULL)
command_obj = GetCommandSP(cmd_cstr, true, false, matches).get();
@@ -702,7 +908,7 @@ CommandInterpreter::ProcessAliasOptionsA
options_string)));
else
{
- int argc = args.GetArgumentCount();
+ const size_t argc = args.GetArgumentCount();
for (size_t i = 0; i < argc; ++i)
if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
option_arg_vector->push_back
@@ -716,6 +922,40 @@ CommandInterpreter::ProcessAliasOptionsA
}
bool
+CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
+{
+ bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
+ if (exact_match)
+ {
+ full_name.assign(cmd);
+ return exact_match;
+ }
+ else
+ {
+ StringList matches;
+ size_t num_alias_matches;
+ num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
+ if (num_alias_matches == 1)
+ {
+ // Make sure this isn't shadowing a command in the regular command space:
+ StringList regular_matches;
+ const bool include_aliases = false;
+ const bool exact = false;
+ CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches));
+ if (cmd_obj_sp || regular_matches.GetSize() > 0)
+ return false;
+ else
+ {
+ full_name.assign (matches.GetStringAtIndex(0));
+ return true;
+ }
+ }
+ else
+ return false;
+ }
+}
+
+bool
CommandInterpreter::AliasExists (const char *cmd)
{
return m_alias_dict.find(cmd) != m_alias_dict.end();
@@ -812,7 +1052,7 @@ CommandInterpreter::GetHelp (CommandRetu
uint32_t cmd_types)
{
CommandObject::CommandMap::const_iterator pos;
- uint32_t max_len = FindLongestCommandWord (m_command_dict);
+ size_t max_len = FindLongestCommandWord (m_command_dict);
if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
{
@@ -895,8 +1135,7 @@ CommandInterpreter::GetCommandObjectForC
else if (cmd_obj->IsMultiwordObject ())
{
// Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
- CommandObject *sub_cmd_obj =
- ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (cmd_word.c_str());
+ CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
if (sub_cmd_obj)
cmd_obj = sub_cmd_obj;
else // cmd_word was not a valid sub-command word, so we are donee
@@ -1154,19 +1393,21 @@ CommandInterpreter::PreprocessCommand (s
target = Host::GetDummyTarget(GetDebugger()).get();
if (target)
{
- const bool coerce_to_id = false;
- const bool unwind_on_error = true;
- const bool keep_in_memory = false;
ValueObjectSP expr_result_valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false)
+ .SetUnwindOnError(true)
+ .SetIgnoreBreakpoints(true)
+ .SetKeepInMemory(false)
+ .SetRunOthers(true)
+ .SetTimeoutUsec(0);
+
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
- exe_ctx.GetFramePtr(),
- eExecutionPolicyOnlyWhenNeeded,
- coerce_to_id,
- unwind_on_error,
- keep_in_memory,
- eNoDynamicValues,
+ exe_ctx.GetFramePtr(),
expr_result_valobj_sp,
- 0 /* no timeout */);
+ options);
+
if (expr_result == eExecutionCompleted)
{
Scalar scalar;
@@ -1213,6 +1454,9 @@ CommandInterpreter::PreprocessCommand (s
case eExecutionInterrupted:
error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
break;
+ case eExecutionHitBreakpoint:
+ error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
+ break;
case eExecutionTimedOut:
error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
break;
@@ -1245,7 +1489,7 @@ CommandInterpreter::HandleCommand (const
std::string command_string (command_line);
std::string original_command_string (command_line);
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
// Make a scoped cleanup object that will clear the crash description string
@@ -1260,7 +1504,6 @@ CommandInterpreter::HandleCommand (const
if (!no_context_switching)
UpdateExecutionContext (override_context);
- // <rdar://problem/11328896>
bool add_to_history;
if (lazy_add_to_history == eLazyBoolCalculate)
add_to_history = (m_command_source_depth == 0);
@@ -1363,10 +1606,11 @@ CommandInterpreter::HandleCommand (const
ExtractCommand (command_string, next_word, suffix, quote_char);
if (cmd_obj == NULL)
{
- if (AliasExists (next_word.c_str()))
+ std::string full_name;
+ if (GetAliasFullName(next_word.c_str(), full_name))
{
std::string alias_result;
- cmd_obj = BuildAliasResult (next_word.c_str(), command_string, alias_result, result);
+ cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
revised_command_line.Printf ("%s", alias_result.c_str());
if (cmd_obj)
{
@@ -1393,7 +1637,7 @@ CommandInterpreter::HandleCommand (const
{
if (cmd_obj->IsMultiwordObject ())
{
- CommandObject *sub_cmd_obj = ((CommandObjectMultiword *) cmd_obj)->GetSubcommandObject (next_word.c_str());
+ CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
if (sub_cmd_obj)
{
actual_cmd_name_len += next_word.length() + 1;
@@ -1422,21 +1666,15 @@ CommandInterpreter::HandleCommand (const
if (cmd_obj == NULL)
{
- uint32_t num_matches = matches.GetSize();
+ const size_t num_matches = matches.GetSize();
if (matches.GetSize() > 1) {
- std::string error_msg;
- error_msg.assign ("Ambiguous command '");
- error_msg.append(next_word.c_str());
- error_msg.append ("'.");
-
- error_msg.append (" Possible matches:");
+ StreamString error_msg;
+ error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
for (uint32_t i = 0; i < num_matches; ++i) {
- error_msg.append ("\n\t");
- error_msg.append (matches.GetStringAtIndex(i));
+ error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
}
- error_msg.append ("\n");
- result.AppendRawError (error_msg.c_str(), error_msg.size());
+ result.AppendRawError (error_msg.GetString().c_str());
} else {
// We didn't have only one match, otherwise we wouldn't get here.
assert(num_matches == 0);
@@ -1604,7 +1842,7 @@ CommandInterpreter::HandleCommand (const
error_msg.append (matches.GetStringAtIndex (i));
}
error_msg.append ("\n");
- result.AppendRawError (error_msg.c_str(), error_msg.size());
+ result.AppendRawError (error_msg.c_str());
}
else
result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
@@ -1784,7 +2022,7 @@ CommandInterpreter::HandleCompletion (co
std::string common_prefix;
matches.LongestCommonPrefix (common_prefix);
- int partial_name_len = command_partial_str.size();
+ const size_t partial_name_len = command_partial_str.size();
// If we matched a unique single command, add a space...
// Only do this if the completer told us this was a complete word, however...
@@ -1931,20 +2169,6 @@ CommandInterpreter::Confirm (const char
return response;
}
-
-void
-CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type)
-{
- CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true);
-
- if (cmd_obj_sp)
- {
- CommandObject *cmd_obj = cmd_obj_sp.get();
- if (cmd_obj->IsCrossRefObject ())
- cmd_obj->AddObject (object_type);
- }
-}
-
OptionArgVectorSP
CommandInterpreter::GetAliasOptions (const char *alias_name)
{
@@ -2038,7 +2262,7 @@ CommandInterpreter::BuildAliasCommandArg
}
OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
- int old_size = cmd_args.GetArgumentCount();
+ const size_t old_size = cmd_args.GetArgumentCount();
std::vector<bool> used (old_size + 1, false);
used[0] = true;
@@ -2288,10 +2512,17 @@ CommandInterpreter::HandleCommands (cons
CommandReturnObject tmp_result;
// If override_context is not NULL, pass no_context_switching = true for
// HandleCommand() since we updated our context already.
+
+ // We might call into a regex or alias command, in which case the add_to_history will get lost. This
+ // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
+ if (!add_to_history)
+ m_command_source_depth++;
bool success = HandleCommand(cmd, add_to_history, tmp_result,
NULL, /* override_context */
true, /* repeat_on_empty_command */
override_context != NULL /* no_context_switching */);
+ if (!add_to_history)
+ m_command_source_depth--;
if (print_results)
{
@@ -2394,8 +2625,14 @@ CommandInterpreter::HandleCommandsFromFi
}
ScriptInterpreter *
-CommandInterpreter::GetScriptInterpreter ()
+CommandInterpreter::GetScriptInterpreter (bool can_create)
{
+ if (m_script_interpreter_ap.get() != NULL)
+ return m_script_interpreter_ap.get();
+
+ if (!can_create)
+ return NULL;
+
// <rdar://problem/11751427>
// we need to protect the initialization of the script interpreter
// otherwise we could end up with two threads both trying to create
@@ -2406,8 +2643,9 @@ CommandInterpreter::GetScriptInterpreter
static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
Mutex::Locker interpreter_lock(g_interpreter_mutex);
- if (m_script_interpreter_ap.get() != NULL)
- return m_script_interpreter_ap.get();
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("Initializing the ScriptInterpreter now\n");
lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
switch (script_lang)
@@ -2422,8 +2660,6 @@ CommandInterpreter::GetScriptInterpreter
case eScriptLanguageNone:
m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
break;
- default:
- break;
};
return m_script_interpreter_ap.get();
@@ -2448,7 +2684,7 @@ CommandInterpreter::OutputFormattedHelpT
const char *word_text,
const char *separator,
const char *help_text,
- uint32_t max_word_len)
+ size_t max_word_len)
{
const uint32_t max_columns = m_debugger.GetTerminalWidth();
@@ -2457,7 +2693,7 @@ CommandInterpreter::OutputFormattedHelpT
strm.IndentMore (indent_size);
StreamString text_strm;
- text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text);
+ text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text);
size_t len = text_strm.GetSize();
const char *text = text_strm.GetData();
@@ -2477,10 +2713,9 @@ CommandInterpreter::OutputFormattedHelpT
// We need to break it up into multiple lines.
bool first_line = true;
int text_width;
- int start = 0;
- int end = start;
- int final_end = strlen (text);
- int sub_len;
+ size_t start = 0;
+ size_t end = start;
+ const size_t final_end = strlen (text);
while (end < final_end)
{
@@ -2505,9 +2740,10 @@ CommandInterpreter::OutputFormattedHelpT
while (end > start
&& text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
end--;
+ assert (end > 0);
}
- sub_len = end - start;
+ const size_t sub_len = end - start;
if (start != 0)
strm.EOL();
if (!first_line)
@@ -2567,54 +2803,53 @@ CommandInterpreter::OutputHelpText (Stre
}
void
-CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
- StringList &commands_found, StringList &commands_help)
+CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
+ StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
{
CommandObject::CommandMap::const_iterator pos;
- CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict;
- CommandObject *sub_cmd_obj;
- for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos)
+ if (search_builtin_commands)
{
- const char * command_name = pos->first.c_str();
- sub_cmd_obj = pos->second.get();
- StreamString complete_command_name;
-
- complete_command_name.Printf ("%s %s", prefix, command_name);
-
- if (sub_cmd_obj->HelpTextContainsWord (search_word))
- {
- commands_found.AppendString (complete_command_name.GetData());
- commands_help.AppendString (sub_cmd_obj->GetHelp());
- }
-
- if (sub_cmd_obj->IsMultiwordObject())
- AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found,
- commands_help);
- }
-
-}
+ for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+ {
+ const char *command_name = pos->first.c_str();
+ CommandObject *cmd_obj = pos->second.get();
-void
-CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
- StringList &commands_help)
-{
- CommandObject::CommandMap::const_iterator pos;
+ if (cmd_obj->HelpTextContainsWord (search_word))
+ {
+ commands_found.AppendString (command_name);
+ commands_help.AppendString (cmd_obj->GetHelp());
+ }
- for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
+ if (cmd_obj->IsMultiwordObject())
+ cmd_obj->AproposAllSubCommands (command_name,
+ search_word,
+ commands_found,
+ commands_help);
+
+ }
+ }
+
+ if (search_user_commands)
{
- const char *command_name = pos->first.c_str();
- CommandObject *cmd_obj = pos->second.get();
-
- if (cmd_obj->HelpTextContainsWord (search_word))
+ for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
{
- commands_found.AppendString (command_name);
- commands_help.AppendString (cmd_obj->GetHelp());
- }
+ const char *command_name = pos->first.c_str();
+ CommandObject *cmd_obj = pos->second.get();
- if (cmd_obj->IsMultiwordObject())
- AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help);
-
+ if (cmd_obj->HelpTextContainsWord (search_word))
+ {
+ commands_found.AppendString (command_name);
+ commands_help.AppendString (cmd_obj->GetHelp());
+ }
+
+ if (cmd_obj->IsMultiwordObject())
+ cmd_obj->AproposAllSubCommands (command_name,
+ search_word,
+ commands_found,
+ commands_help);
+
+ }
}
}
@@ -2642,7 +2877,7 @@ CommandInterpreter::DumpHistory (Stream
void
CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const
{
- const size_t last_idx = std::min<size_t>(m_command_history.size(), end + 1);
+ const size_t last_idx = std::min<size_t>(m_command_history.size(), end==UINT32_MAX ? UINT32_MAX : end + 1);
for (size_t i = start; i < last_idx; i++)
{
if (!m_command_history[i].empty())
@@ -2661,7 +2896,7 @@ CommandInterpreter::FindHistoryString (c
if (input_str[1] == '-')
{
bool success;
- uint32_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
+ size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success);
if (!success)
return NULL;
if (idx > m_command_history.size())
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandObject.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandObject.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandObject.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/CommandObject.h"
#include <string>
@@ -167,7 +169,7 @@ CommandObject::ParseOptions
Error error;
options->NotifyOptionParsingStarting();
- // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
+ // ParseOptions calls getopt_long_only, which always skips the zero'th item in the array and starts at position 1,
// so we need to push a dummy value into position zero.
args.Unshift("dummy_string");
error = args.ParseOptions (*options);
@@ -206,8 +208,77 @@ CommandObject::ParseOptions
bool
-CommandObject::CheckFlags (CommandReturnObject &result)
+CommandObject::CheckRequirements (CommandReturnObject &result)
{
+#ifdef LLDB_CONFIGURATION_DEBUG
+ // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
+ // has shared pointers to the target, process, thread and frame and we don't
+ // want any CommandObject instances to keep any of these objects around
+ // longer than for a single command. Every command should call
+ // CommandObject::Cleanup() after it has completed
+ assert (m_exe_ctx.GetTargetPtr() == NULL);
+ assert (m_exe_ctx.GetProcessPtr() == NULL);
+ assert (m_exe_ctx.GetThreadPtr() == NULL);
+ assert (m_exe_ctx.GetFramePtr() == NULL);
+#endif
+
+ // Lock down the interpreter's execution context prior to running the
+ // command so we guarantee the selected target, process, thread and frame
+ // can't go away during the execution
+ m_exe_ctx = m_interpreter.GetExecutionContext();
+
+ const uint32_t flags = GetFlags().Get();
+ if (flags & (eFlagRequiresTarget |
+ eFlagRequiresProcess |
+ eFlagRequiresThread |
+ eFlagRequiresFrame |
+ eFlagTryTargetAPILock ))
+ {
+
+ if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope())
+ {
+ result.AppendError (GetInvalidTargetDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope())
+ {
+ result.AppendError (GetInvalidProcessDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope())
+ {
+ result.AppendError (GetInvalidThreadDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope())
+ {
+ result.AppendError (GetInvalidFrameDescription());
+ return false;
+ }
+
+ if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL))
+ {
+ result.AppendError (GetInvalidRegContextDescription());
+ return false;
+ }
+
+ if (flags & eFlagTryTargetAPILock)
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false)
+ {
+ result.AppendError ("failed to get API lock");
+ return false;
+ }
+ }
+ }
+ }
+
if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
@@ -224,7 +295,6 @@ CommandObject::CheckFlags (CommandReturn
else
{
StateType state = process->GetState();
-
switch (state)
{
case eStateInvalid:
@@ -261,6 +331,14 @@ CommandObject::CheckFlags (CommandReturn
return true;
}
+void
+CommandObject::Cleanup ()
+{
+ m_exe_ctx.Clear();
+ m_api_locker.Unlock();
+}
+
+
class CommandDictCommandPartialMatch
{
public:
@@ -272,13 +350,9 @@ class CommandDictCommandPartialMatch
{
// A NULL or empty string matches everything.
if (m_match_str == NULL || *m_match_str == '\0')
- return 1;
+ return true;
- size_t found = map_element.first.find (m_match_str, 0);
- if (found == std::string::npos)
- return 0;
- else
- return found == 0;
+ return map_element.first.find (m_match_str, 0) == 0;
}
private:
@@ -341,7 +415,7 @@ CommandObject::HandleCompletion
// I stick an element on the end of the input, because if the last element is
- // option that requires an argument, getopt_long will freak out.
+ // option that requires an argument, getopt_long_only will freak out.
input.AppendArgument ("<FAKE-VALUE>");
@@ -377,23 +451,19 @@ CommandObject::HandleCompletion
bool
CommandObject::HelpTextContainsWord (const char *search_word)
{
- const char *short_help;
- const char *long_help;
- const char *syntax_help;
std::string options_usage_help;
-
bool found_word = false;
- short_help = GetHelp();
- long_help = GetHelpLong();
- syntax_help = GetSyntax();
+ const char *short_help = GetHelp();
+ const char *long_help = GetHelpLong();
+ const char *syntax_help = GetSyntax();
- if (strcasestr (short_help, search_word))
+ if (short_help && strcasestr (short_help, search_word))
found_word = true;
- else if (strcasestr (long_help, search_word))
+ else if (long_help && strcasestr (long_help, search_word))
found_word = true;
- else if (strcasestr (syntax_help, search_word))
+ else if (syntax_help && strcasestr (syntax_help, search_word))
found_word = true;
if (!found_word
@@ -630,6 +700,23 @@ CommandObject::LookupArgumentName (const
}
static const char *
+RegisterNameHelpTextCallback ()
+{
+ return "Register names can be specified using the architecture specific names. "
+ "They can also be specified using generic names. Not all generic entities have "
+ "registers backing them on all architectures. When they don't the generic name "
+ "will return an error.\n"
+ "The generic names defined in lldb are:\n"
+ "\n"
+ "pc - program counter register\n"
+ "ra - return address register\n"
+ "fp - frame pointer register\n"
+ "sp - stack pointer register\n"
+ "flags - the flags register\n"
+ "arg{1-6} - integer argument passing registers.\n";
+}
+
+static const char *
BreakpointIDHelpTextCallback ()
{
return "Breakpoint ID's consist major and minor numbers; the major number "
@@ -729,6 +816,33 @@ FormatHelpTextCallback ()
}
static const char *
+LanguageTypeHelpTextCallback ()
+{
+ static char* help_text_ptr = NULL;
+
+ if (help_text_ptr)
+ return help_text_ptr;
+
+ StreamString sstr;
+ sstr << "One of the following languages:\n";
+
+ for (unsigned int l = eLanguageTypeUnknown; l < eNumLanguageTypes; ++l)
+ {
+ sstr << " " << LanguageRuntime::GetNameForLanguageType(static_cast<LanguageType>(l)) << "\n";
+ }
+
+ sstr.Flush();
+
+ std::string data = sstr.GetString();
+
+ help_text_ptr = new char[data.length()+1];
+
+ data.copy(help_text_ptr, data.length());
+
+ return help_text_ptr;
+}
+
+static const char *
SummaryStringHelpTextCallback()
{
return
@@ -846,14 +960,16 @@ CommandObjectParsed::Execute (const char
cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
}
- if (!CheckFlags(result))
- return false;
-
- if (!ParseOptions (cmd_args, result))
- return false;
+ if (CheckRequirements(result))
+ {
+ if (ParseOptions (cmd_args, result))
+ {
+ // Call the command-specific version of 'Execute', passing it the already processed arguments.
+ handled = DoExecute (cmd_args, result);
+ }
+ }
- // Call the command-specific version of 'Execute', passing it the already processed arguments.
- handled = DoExecute (cmd_args, result);
+ Cleanup();
}
return handled;
}
@@ -874,10 +990,10 @@ CommandObjectRaw::Execute (const char *a
}
if (!handled)
{
- if (!CheckFlags(result))
- return false;
- else
+ if (CheckRequirements(result))
handled = DoExecute (args_string, result);
+
+ Cleanup();
}
return handled;
}
@@ -900,6 +1016,7 @@ CommandObject::ArgumentTableEntry
CommandObject::g_arguments_data[] =
{
{ eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." },
+ { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { NULL, false }, "An expression that resolves to an address." },
{ eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." },
{ eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" },
{ eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." },
@@ -910,6 +1027,8 @@ CommandObject::g_arguments_data[] =
{ eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." },
{ eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." },
{ eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
+ { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { NULL, false }, "A directory name." },
+ { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { NULL, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
{ eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL },
@@ -919,9 +1038,10 @@ CommandObject::g_arguments_data[] =
{ eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." },
{ eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." },
+ { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function or symbol." },
{ eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, NULL },
{ eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." },
- { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { NULL, false }, "A source language name." },
+ { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, NULL },
{ eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." },
{ eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
{ eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
@@ -933,7 +1053,6 @@ CommandObject::g_arguments_data[] =
{ eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." },
- { eArgTypePath, "path", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
{ eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { NULL, false }, "Permissions given as an octal number (e.g. 755)." },
{ eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { NULL, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
{ eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." },
@@ -943,7 +1062,7 @@ CommandObject::g_arguments_data[] =
{ eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." },
{ eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." },
{ eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." },
- { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." },
+ { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, NULL },
{ eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." },
{ eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." },
{ eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectRegexCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectRegexCommand.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectRegexCommand.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectRegexCommand.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
// C Includes
@@ -28,10 +30,12 @@ CommandObjectRegexCommand::CommandObject
const char *name,
const char *help,
const char *syntax,
- uint32_t max_matches
+ uint32_t max_matches,
+ uint32_t completion_type_mask
) :
CommandObjectRaw (interpreter, name, help, syntax),
m_max_matches (max_matches),
+ m_completion_type_mask (completion_type_mask),
m_entries ()
{
}
@@ -56,7 +60,9 @@ CommandObjectRegexCommand::DoExecute
EntryCollection::const_iterator pos, end = m_entries.end();
for (pos = m_entries.begin(); pos != end; ++pos)
{
- if (pos->regex.Execute (command, m_max_matches))
+ RegularExpression::Match regex_match(m_max_matches);
+
+ if (pos->regex.Execute (command, ®ex_match))
{
std::string new_command(pos->command);
std::string match_str;
@@ -64,7 +70,7 @@ CommandObjectRegexCommand::DoExecute
size_t idx, percent_var_idx;
for (uint32_t match_idx=1; match_idx <= m_max_matches; ++match_idx)
{
- if (pos->regex.GetMatchAtIndex (command, match_idx, match_str))
+ if (regex_match.GetMatchAtIndex (command, match_idx, match_str))
{
const int percent_var_len = ::snprintf (percent_var, sizeof(percent_var), "%%%u", match_idx);
for (idx = 0; (percent_var_idx = new_command.find(percent_var, idx)) != std::string::npos; )
@@ -76,14 +82,20 @@ CommandObjectRegexCommand::DoExecute
}
}
// Interpret the new command and return this as the result!
- result.GetOutputStream().Printf("%s\n", new_command.c_str());
- return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result);
+ if (m_interpreter.GetExpandRegexAliases())
+ result.GetOutputStream().Printf("%s\n", new_command.c_str());
+ // Pass in true for "no context switching". The command that called us should have set up the context
+ // appropriately, we shouldn't have to redo that.
+ return m_interpreter.HandleCommand(new_command.c_str(), eLazyBoolCalculate, result, NULL, true, true);
}
}
result.SetStatus(eReturnStatusFailed);
- result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
- command,
- m_cmd_name.c_str());
+ if (GetSyntax() != NULL)
+ result.AppendError (GetSyntax());
+ else
+ result.AppendErrorWithFormat ("Command contents '%s' failed to match any regular expression in the '%s' regex command.\n",
+ command,
+ m_cmd_name.c_str());
return false;
}
result.AppendError("empty command passed to regular expression command");
@@ -106,3 +118,33 @@ CommandObjectRegexCommand::AddRegexComma
m_entries.pop_back();
return false;
}
+
+int
+CommandObjectRegexCommand::HandleCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches)
+{
+ if (m_completion_type_mask)
+ {
+ std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
+ CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
+ m_completion_type_mask,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ NULL,
+ word_complete,
+ matches);
+ return matches.GetSize();
+ }
+ else
+ {
+ matches.Clear();
+ word_complete = false;
+ }
+ return 0;
+}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "CommandObjectScript.h"
// C Includes
@@ -14,13 +16,14 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/Core/DataVisualization.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
using namespace lldb;
using namespace lldb_private;
@@ -33,8 +36,7 @@ CommandObjectScript::CommandObjectScript
CommandObjectRaw (interpreter,
"script",
"Pass an expression to the script interpreter for evaluation and return the results. Drop into the interactive interpreter if no expression is given.",
- "script [<script-expression-for-evaluation>]"),
- m_script_lang (script_lang)
+ "script [<script-expression-for-evaluation>]")
{
}
@@ -49,12 +51,26 @@ CommandObjectScript::DoExecute
CommandReturnObject &result
)
{
+#ifdef LLDB_DISABLE_PYTHON
+ // if we ever support languages other than Python this simple #ifdef won't work
+ result.AppendError("your copy of LLDB does not support scripting.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+#else
+ if (m_interpreter.GetDebugger().GetScriptLanguage() == lldb::eScriptLanguageNone)
+ {
+ result.AppendError("the script-lang setting is set to none - scripting not available");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
ScriptInterpreter *script_interpreter = m_interpreter.GetScriptInterpreter ();
if (script_interpreter == NULL)
{
result.AppendError("no script interpreter");
result.SetStatus (eReturnStatusFailed);
+ return false;
}
DataVisualization::ForceUpdate(); // script might change Python code we use for formatting.. make sure we keep up to date with it
@@ -67,10 +83,11 @@ CommandObjectScript::DoExecute
}
// We can do better when reporting the status of one-liner script execution.
- if (script_interpreter->ExecuteOneLine (command, &result, true))
+ if (script_interpreter->ExecuteOneLine (command, &result))
result.SetStatus(eReturnStatusSuccessFinishNoResult);
else
result.SetStatus(eReturnStatusFailed);
return result.Succeeded();
+#endif
}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.h (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandObjectScript.h Thu Jun 6 19:06:43 2013
@@ -35,9 +35,6 @@ public:
protected:
virtual bool
DoExecute (const char *command, CommandReturnObject &result);
-
-private:
- lldb::ScriptLanguage m_script_lang;
};
} // namespace lldb_private
Modified: lldb/branches/lldb-platform-work/source/Interpreter/CommandReturnObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/CommandReturnObject.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/CommandReturnObject.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/CommandReturnObject.cpp Thu Jun 6 19:06:43 2013
@@ -104,46 +104,37 @@ CommandReturnObject::AppendWarningWithFo
}
void
-CommandReturnObject::AppendMessage (const char *in_string, int len)
+CommandReturnObject::AppendMessage (const char *in_string)
{
if (!in_string)
return;
- if (len < 0)
- len = ::strlen (in_string);
- GetOutputStream().Printf("%*.*s\n", len, len, in_string);
+ GetOutputStream().Printf("%s\n", in_string);
}
void
-CommandReturnObject::AppendWarning (const char *in_string, int len)
+CommandReturnObject::AppendWarning (const char *in_string)
{
- if (!in_string)
+ if (!in_string || *in_string == '\0')
return;
- if (len < 0)
- len = ::strlen (in_string);
- GetErrorStream().Printf("warning: %*.*s\n", len, len, in_string);
+ GetErrorStream().Printf("warning: %s\n", in_string);
}
// Similar to AppendWarning, but do not prepend 'warning: ' to message, and
// don't append "\n" to the end of it.
void
-CommandReturnObject::AppendRawWarning (const char *in_string, int len)
+CommandReturnObject::AppendRawWarning (const char *in_string)
{
- if (!in_string)
- return;
- if (len < 0)
- len = ::strlen (in_string);
- GetErrorStream().Printf("%*.*s", len, len, in_string);
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(in_string);
}
void
-CommandReturnObject::AppendError (const char *in_string, int len)
+CommandReturnObject::AppendError (const char *in_string)
{
- if (!in_string)
+ if (!in_string || *in_string == '\0')
return;
- if (len < 0)
- len = ::strlen (in_string);
- GetErrorStream().Printf ("error: %*.*s\n", len, len, in_string);
+ GetErrorStream().Printf ("error: %s\n", in_string);
}
void
@@ -159,13 +150,10 @@ CommandReturnObject::SetError (const Err
// don't append "\n" to the end of it.
void
-CommandReturnObject::AppendRawError (const char *in_string, int len)
+CommandReturnObject::AppendRawError (const char *in_string)
{
- if (!in_string)
- return;
- if (len < 0)
- len = ::strlen (in_string);
- GetErrorStream().Printf ("%*.*s", len, len, in_string);
+ if (in_string && in_string[0])
+ GetErrorStream().PutCString(in_string);
}
void
Modified: lldb/branches/lldb-platform-work/source/Interpreter/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/Makefile Thu Jun 6 19:06:43 2013
@@ -16,172 +16,28 @@ BUILT_SOURCES := LLDBWrapPython.cpp
include $(LLDB_LEVEL)/Makefile
-include $(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.d
-PYTHON_DIR := $(LibDir)/python/lldb
-ifeq ($(HOST_OS),Darwin)
-PYTHON_DEST_DIR := $(DESTDIR)/$(call realpath,/Library/Python/$(shell python -c 'import sys; print sys.version[:3]')/site-packages)/lldb
-else
-PYTHON_DEST_DIR := $(DESTDIR)/$(call realpath,$(shell python -c 'import sys; print sys.exec_prefix')/lib/python$(shell python -c 'import sys; print sys.version[:3]')/site-packages)/lldb
-endif
-LLDB_SWIG_INCLUDE_DIRS:= -I"$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/include" -I./.
-LIBLLDB := $(LibDir)/liblldb$(SHLIBEXT)
-INST_LIBLLDB := $(PROJ_libdir)/liblldb$(SHLIBEXT)
-
-# Subpackages of the main LLDB package
-LLDB_SUBPACKAGES := FORMATTERS FORMATTERS_CPP FORMATTERS_OBJC RUNTIME RUNTIME_OBJC UTILS
-# lldb.formatters
-LLDB_PACKAGE_FORMATTERS := formatters
-LLDB_PACKAGE_FORMATTERS_FILES := $(addprefix \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/summaries/cocoa/, \
- cache.py metrics.py attrib_fromdict.py Logger.py)
-# lldb.formatters.cpp
-LLDB_PACKAGE_FORMATTERS_CPP := formatters/cpp
-LLDB_PACKAGE_FORMATTERS_CPP_FILES := $(addprefix \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/synthetic/,gnu_libstdcpp.py libcxx.py)
-# lldb.formatters.objc
-LLDB_PACKAGE_FORMATTERS_OBJC := formatters/objc
-LLDB_PACKAGE_FORMATTERS_OBJC_FILES := \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/summaries/cocoa/Selector.py \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/summaries/objc.py \
- $(addprefix $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/summaries/cocoa/, \
- Class.py CFArray.py CFBag.py CFBinaryHeap.py CFBitVector.py \
- CFDictionary.py CFString.py NSBundle.py NSData.py NSDate.py \
- NSException.py NSIndexSet.py NSMachPort.py NSNotification.py \
- NSNumber.py NSSet.py NSURL.py \
- )
-# lldb.runtime
-LLDB_PACKAGE_RUNTIME := runtime
-LLDB_PACKAGE_RUNTIME_FILES :=
-# lldb.runtime.objc
-LLDB_PACKAGE_RUNTIME_OBJC := runtime/objc
-LLDB_PACKAGE_RUNTIME_OBJC_FILES := \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/summaries/cocoa/objc_runtime.py
-# lldb.utils
-LLDB_PACKAGE_UTILS := utils
-LLDB_PACKAGE_UTILS_FILES := \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/python/symbolication.py
-
-ifeq ($(HOST_OS),Darwin)
-# Additional packages for Darwin/Mac OS X
-LLDB_SUBPACKAGES += MACOSX
-# lldb.macosx
-LLDB_PACKAGE_MACOSX := macosx
-LLDB_PACKAGE_MACOSX_FILES := $(addprefix \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/, python/crashlog.py darwin/heap_find/heap.py \
-)
-endif
-
-LLDB_ALL_SUBPACKAGE_FILES := $(foreach subpackage,$(LLDB_SUBPACKAGES),$(LLDB_PACKAGE_$(subpackage)_FILES))
-LLDB_ALL_INSTALLED_SUBPACKAGE_FILES := $(foreach subpackage,$(LLDB_SUBPACKAGES),$(addprefix $(LLDB_PACKAGE_$(subpackage))/,$(notdir $(LLDB_PACKAGE_$(subpackage)_FILES))))
-
-comma := ,
-LLDB_COPY_PACKAGE = $(Verb) \
-$(foreach subpackage,$(LLDB_SUBPACKAGES), \
- init_file="$(PYTHON_DIR)/$(LLDB_PACKAGE_$(subpackage))/__init__.py"; \
- $(MKDIR) "$(PYTHON_DIR)/$(LLDB_PACKAGE_$(subpackage))"; \
- $(foreach file,$(LLDB_PACKAGE_$(subpackage)_FILES), \
- $(CP) "$(file)" "$(PYTHON_DIR)/$(LLDB_PACKAGE_$(subpackage))"; \
- ) \
- echo "__all__ = [$(patsubst %,\"%\"$(comma),\
- $(basename $(notdir $(LLDB_PACKAGE_$(subpackage)_FILES))))]" >$$init_file; \
- echo "for x in __all__:" >>$$init_file; \
- echo " __import__('lldb.$(subst /,.,$(LLDB_PACKAGE_$(subpackage))).'+x)" >>$$init_file; \
-)
-
-LLDB_INSTALL_SUBPACKAGES = $(Verb) \
-$(foreach subpackage,$(LLDB_SUBPACKAGES), \
- $(MKDIR) $(PYTHON_DEST_DIR)/$(LLDB_PACKAGE_$(subpackage)); \
- $(DataInstall) $(PYTHON_DIR)/$(LLDB_PACKAGE_$(subpackage))/__init__.py \
- $(PYTHON_DEST_DIR)/$(LLDB_PACKAGE_$(subpackage))/__init__.py; \
-) \
-$(foreach file,$(LLDB_ALL_INSTALLED_SUBPACKAGE_FILES), \
- $(DataInstall) $(PYTHON_DIR)/$(file) $(PYTHON_DEST_DIR)/$(file); \
-)
-
-ifeq ($(HOST_OS),Darwin)
-# Install the heap_find sources, too.
-LLDB_INSTALL_SUBPACKAGES += $(MKDIR) $(PYTHON_DEST_DIR)/macosx/heap/; \
-$(DataInstall) $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/darwin/heap_find/heap/heap_find.cpp \
- $(PYTHON_DEST_DIR)/macosx/heap/heap_find.cpp; \
-$(DataInstall) $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/examples/darwin/heap_find/heap/Makefile \
- $(PYTHON_DEST_DIR)/macosx/heap/Makefile;
-endif
-
-# We need Swig to process stdint.h, but by default it will not inspect system
-# include directories. The following should cover the standard locations on
-# most platforms.
-LLDB_SWIG_INCLUDE_DIRS += -I"/usr/local/include"
-LLDB_SWIG_INCLUDE_DIRS += -I"/usr/include"
-
-# On Darwin, stdint.h might only be in the compiler subdirectory. Unfortunately,
-# swig doesn't currently seem able to understand Clang's stdint.h, so we have to
-# point at the GCC one.
-ifeq ($(HOST_OS),Darwin)
-LLDB_SWIG_INCLUDE_DIRS += -I"/usr/include/gcc/darwin/4.2"
-endif
-
-ifndef DISABLE_AUTO_DEPENDENCIES
-
-SWIG_DEPEND_OPTIONS = -MMD -MF "$(PROJ_OBJ_DIR)/$*.cpp.d.tmp"
-CPP_DEPEND_MOVEFILE = then $(MV) -f "$(PROJ_OBJ_DIR)/$*.cpp.d.tmp" "$(PROJ_OBJ_DIR)/$*.cpp.d"; \
- else $(RM) -f "$(PROJ_OBJ_DIR)/$*.cpp.d.tmp"; exit 1; fi
+# Drop -Wfour-char-constants, which we are not currently clean with.
+EXTRA_OPTIONS += -Wno-four-char-constants
-LLDBWrapPython.cpp: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/edit-swig-python-wrapper-file.py
- $(Echo) Generating LLDBWrapPython.cpp
- $(Verb) $(MKDIR) $(PYTHON_DIR)
- $(Verb) if swig -c++ -shadow -python $(LLDB_SWIG_INCLUDE_DIRS) \
- -D__STDC_LIMIT_MACROS -outdir "$(PYTHON_DIR)" \
- $(SWIG_DEPEND_OPTIONS) \
- -o LLDBWrapPython.cpp "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/lldb.swig" ; \
- $(CPP_DEPEND_MOVEFILE)
- $(Verb) python "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py" \
- "$(PYTHON_DIR)"
- $(Verb) python "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/edit-swig-python-wrapper-file.py" \
- "$(PROJ_OBJ_DIR)"
- $(Verb) if test -f "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.edited"; then \
- $(MV) "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.edited" \
- "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp"; fi
- $(Verb) $(MV) "$(PYTHON_DIR)/lldb.py" "$(PYTHON_DIR)/__init__.py"
- $(Verb) $(CP) "$(PROJ_SRC_DIR)/embedded_interpreter.py" "$(PYTHON_DIR)"
- $(Verb) $(RM) -f $(PYTHON_DIR)/_lldb.so
- $(Verb) $(AliasTool) $(LIBLLDB) $(PYTHON_DIR)/_lldb.so
- $(LLDB_COPY_PACKAGE)
+# Drop -Wself-assign, -Wmissing-field-initializers and -Wsometimes-uninitialized,
+# which we are not currently clean with (due to SWIG generated cpp source).
+EXTRA_OPTIONS += -Wno-missing-field-initializers -Wno-self-assign -Wno-sometimes-uninitialized
-else
+# edit-swig-python-wrapper-file.py needs $(SRCROOT)
+export SRCROOT := $(PROJ_SRC_DIR)/$(LLDB_LEVEL)
-LLDBWrapPython.cpp: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py \
- $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/edit-swig-python-wrapper-file.py
- $(Echo) Generating LLDBWrapPython.cpp
- $(Verb) $(MKDIR) $(PYTHON_DIR)
- $(Verb) swig -c++ -shadow -python $(LLDB_SWIG_INCLUDE_DIRS) \
- -D__STDC_LIMIT_MACROS -outdir "$(PYTHON_DIR)" \
- -o LLDBWrapPython.cpp "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/lldb.swig"
- $(Verb) python "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py" \
- "$(PYTHON_DIR)"
- $(Verb) python "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/edit-swig-python-wrapper-file.py" \
- "$(PROJ_OBJ_DIR)"
- $(Verb) if test -f "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.edited"; then \
- $(MV) "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp.edited" \
- "$(PROJ_OBJ_DIR)/LLDBWrapPython.cpp"; fi
- $(Verb) $(MV) "$(PYTHON_DIR)/lldb.py" "$(PYTHON_DIR)/__init__.py"
- $(Verb) $(CP) "$(PROJ_SRC_DIR)/embedded_interpreter.py" "$(PYTHON_DIR)"
- $(Verb) $(RM) -f $(PYTHON_DIR)/_lldb.so
- $(Verb) $(AliasTool) $(LIBLLDB) $(PYTHON_DIR)/_lldb.so
- $(LLDB_COPY_PACKAGE)
+PYTHON_DIR := $(PROJ_OBJ_ROOT)/$(BuildMode)
-endif
+LLDBWrapPython.cpp lldb.py: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/modify-python-lldb.py \
+ $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/edit-swig-python-wrapper-file.py \
+ $(wildcard $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/Python/interface/*.i)
+ $(Echo) Generating LLDBWrapPython.cpp
+ $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/build-swig-wrapper-classes.sh" "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "$(PROJ_OBJ_DIR)" "$(PROJ_OBJ_DIR)" "$(PYTHON_DIR)" -m $(if $(DISABLE_AUTO_DEPENDENCIES),,-M)
+ $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/finish-swig-wrapper-classes.sh" "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "$(PROJ_OBJ_DIR)" "$(PROJ_OBJ_DIR)" "$(PYTHON_DIR)" -m
-install-local:: $(PYTHON_DIR)/__init__.py $(PYTHON_DIR)/embedded_interpreter.py \
- $(addprefix $(PYTHON_DIR)/,$(LLDB_ALL_INSTALLED_SUBPACKAGE_FILES))
+install-local:: lldb.py
$(Echo) Installing $(BuildMode) LLDB python modules
- $(Verb) $(MKDIR) $(PYTHON_DEST_DIR)
- $(Verb) $(DataInstall) $(PYTHON_DIR)/__init__.py $(PYTHON_DEST_DIR)/__init__.py
- $(Verb) $(DataInstall) $(PYTHON_DIR)/embedded_interpreter.py $(PYTHON_DEST_DIR)/embedded_interpreter.py
- $(Verb) $(RM) -f $(PYTHON_DEST_DIR)/_lldb.so
- $(Verb) $(AliasTool) $(INST_LIBLLDB) $(PYTHON_DEST_DIR)/_lldb.so
- $(LLDB_INSTALL_SUBPACKAGES)
+ $(Verb) "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/finish-swig-wrapper-classes.sh" "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)" "$(PROJ_OBJ_DIR)" "$(PROJ_OBJ_DIR)" "" -m
clean-local::
- $(Verb) $(RM) -f LLDBWrapPython.cpp $(PYTHON_DIR)/_lldb.so \
- $(PYTHON_DIR)/embedded_interpreter.py $(PYTHON_DIR)/__init__.py \
- $(addprefix $(PYTHON_DIR)/,$(LLDB_ALL_INSTALLED_SUBPACKAGE_FILES))
+ $(Verb) $(RM) -f LLDBWrapPython.cpp lldb.py
Removed: lldb/branches/lldb-platform-work/source/Interpreter/NamedOptionValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/NamedOptionValue.cpp?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/NamedOptionValue.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/NamedOptionValue.cpp (removed)
@@ -1,503 +0,0 @@
-//===-- NamedOptionValue.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Interpreter/NamedOptionValue.h"
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/FormatManager.h"
-#include "lldb/Core/State.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Interpreter/Args.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-//-------------------------------------------------------------------------
-// OptionValue
-//-------------------------------------------------------------------------
-
-// Get this value as a uint64_t value if it is encoded as a boolean,
-// uint64_t or int64_t. Other types will cause "fail_value" to be
-// returned
-uint64_t
-OptionValue::GetUInt64Value (uint64_t fail_value, bool *success_ptr)
-{
- if (success_ptr)
- *success_ptr = true;
- switch (GetType())
- {
- case OptionValue::eTypeBoolean: return static_cast<OptionValueBoolean *>(this)->GetCurrentValue();
- case OptionValue::eTypeSInt64: return static_cast<OptionValueSInt64 *>(this)->GetCurrentValue();
- case OptionValue::eTypeUInt64: return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue();
- default:
- break;
- }
- if (success_ptr)
- *success_ptr = false;
- return fail_value;
-}
-
-
-OptionValueBoolean *
-OptionValue::GetAsBoolean ()
-{
- if (GetType () == OptionValue::eTypeBoolean)
- return static_cast<OptionValueBoolean *>(this);
- return NULL;
-}
-
-OptionValueSInt64 *
-OptionValue::GetAsSInt64 ()
-{
- if (GetType () == OptionValue::eTypeSInt64)
- return static_cast<OptionValueSInt64 *>(this);
- return NULL;
-}
-
-OptionValueUInt64 *
-OptionValue::GetAsUInt64 ()
-{
- if (GetType () == OptionValue::eTypeUInt64)
- return static_cast<OptionValueUInt64 *>(this);
- return NULL;
-}
-
-OptionValueString *
-OptionValue::GetAsString ()
-{
- if (GetType () == OptionValue::eTypeString)
- return static_cast<OptionValueString *>(this);
- return NULL;
-}
-
-OptionValueFileSpec *
-OptionValue::GetAsFileSpec ()
-{
- if (GetType () == OptionValue::eTypeFileSpec)
- return static_cast<OptionValueFileSpec *>(this);
- return NULL;
-
-}
-
-OptionValueFormat *
-OptionValue::GetAsFormat ()
-{
- if (GetType () == OptionValue::eTypeFormat)
- return static_cast<OptionValueFormat *>(this);
- return NULL;
-}
-
-OptionValueUUID *
-OptionValue::GetAsUUID ()
-{
- if (GetType () == OptionValue::eTypeUUID)
- return static_cast<OptionValueUUID *>(this);
- return NULL;
-
-}
-
-
-OptionValueArray *
-OptionValue::GetAsArray ()
-{
- if (GetType () == OptionValue::eTypeArray)
- return static_cast<OptionValueArray *>(this);
- return NULL;
-}
-
-OptionValueDictionary *
-OptionValue::GetAsDictionary ()
-{
- if (GetType () == OptionValue::eTypeDictionary)
- return static_cast<OptionValueDictionary *>(this);
- return NULL;
-}
-
-const char *
-OptionValue::GetStringValue (const char *fail_value)
-{
- OptionValueString *option_value = GetAsString ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-uint64_t
-OptionValue::GetUInt64Value (uint64_t fail_value)
-{
- OptionValueUInt64 *option_value = GetAsUInt64 ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-lldb::Format
-OptionValue::GetFormatValue (lldb::Format fail_value)
-{
- OptionValueFormat *option_value = GetAsFormat ();
- if (option_value)
- return option_value->GetCurrentValue();
- return fail_value;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueCollection
-//-------------------------------------------------------------------------
-
-void
-OptionValueCollection::GetQualifiedName (Stream &strm)
-{
- if (m_parent)
- {
- m_parent->GetQualifiedName (strm);
- strm.PutChar('.');
- }
- strm << m_name;
-}
-
-
-//-------------------------------------------------------------------------
-// OptionValueBoolean
-//-------------------------------------------------------------------------
-void
-OptionValueBoolean::DumpValue (Stream &strm)
-{
- strm.PutCString (m_current_value ? "true" : "false");
-}
-
-Error
-OptionValueBoolean::SetValueFromCString (const char *value_cstr)
-{
- Error error;
- bool success = false;
- bool value = Args::StringToBoolean(value_cstr, false, &success);
- if (success)
- {
- m_value_was_set = true;
- m_current_value = value;
- }
- else
- {
- if (value_cstr == NULL)
- error.SetErrorString ("invalid boolean string value: NULL");
- else if (value_cstr[0] == '\0')
- error.SetErrorString ("invalid boolean string value <empty>");
- else
- error.SetErrorStringWithFormat ("invalid boolean string value: '%s'", value_cstr);
- }
- return error;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueSInt64
-//-------------------------------------------------------------------------
-void
-OptionValueSInt64::DumpValue (Stream &strm)
-{
- strm.Printf ("%lli", m_current_value);
-}
-
-Error
-OptionValueSInt64::SetValueFromCString (const char *value_cstr)
-{
-
- Error error;
- bool success = false;
- int64_t value = Args::StringToSInt64 (value_cstr, 0, 0, &success);
- if (success)
- {
- m_value_was_set = true;
- m_current_value = value;
- }
- else
- {
- error.SetErrorStringWithFormat ("invalid int64_t string value: '%s'", value_cstr);
- }
- return error;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueUInt64
-//-------------------------------------------------------------------------
-
-lldb::OptionValueSP
-OptionValueUInt64::Create (const char *value_cstr, Error &error)
-{
- lldb::OptionValueSP value_sp (new OptionValueUInt64());
- error = value_sp->SetValueFromCString (value_cstr);
- if (error.Fail())
- value_sp.reset();
- return value_sp;
-}
-
-
-void
-OptionValueUInt64::DumpValue (Stream &strm)
-{
- strm.Printf ("0x%llx", m_current_value);
-}
-
-Error
-OptionValueUInt64::SetValueFromCString (const char *value_cstr)
-{
- Error error;
- bool success = false;
- uint64_t value = Args::StringToUInt64 (value_cstr, 0, 0, &success);
- if (success)
- {
- m_value_was_set = true;
- m_current_value = value;
- }
- else
- {
- error.SetErrorStringWithFormat ("invalid uint64_t string value: '%s'", value_cstr);
- }
- return error;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueDictionary
-//-------------------------------------------------------------------------
-void
-OptionValueString::DumpValue (Stream &strm)
-{
- strm.Printf ("\"%s\"", m_current_value.c_str());
-}
-
-Error
-OptionValueString::SetValueFromCString (const char *value_cstr)
-{
- m_value_was_set = true;
- SetCurrentValue (value_cstr);
- return Error ();
-}
-
-//-------------------------------------------------------------------------
-// OptionValueFileSpec
-//-------------------------------------------------------------------------
-void
-OptionValueFileSpec::DumpValue (Stream &strm)
-{
- if (m_current_value)
- {
- if (m_current_value.GetDirectory())
- {
- strm << '"' << m_current_value.GetDirectory();
- if (m_current_value.GetFilename())
- strm << '/' << m_current_value.GetFilename();
- strm << '"';
- }
- else
- {
- strm << '"' << m_current_value.GetFilename() << '"';
- }
- }
-}
-
-Error
-OptionValueFileSpec::SetValueFromCString (const char *value_cstr)
-{
- if (value_cstr && value_cstr[0])
- m_current_value.SetFile(value_cstr, false);
- else
- m_current_value.Clear();
- m_value_was_set = true;
- return Error();
-}
-
-//-------------------------------------------------------------------------
-// OptionValueFileSpecList
-//-------------------------------------------------------------------------
-void
-OptionValueFileSpecList::DumpValue (Stream &strm)
-{
- m_current_value.Dump(&strm, "\n");
-}
-
-Error
-OptionValueFileSpecList::SetValueFromCString (const char *value_cstr)
-{
- if (value_cstr && value_cstr[0])
- {
- FileSpec file (value_cstr, false);
- m_current_value.Append(file);
- }
- m_value_was_set = true;
- return Error();
-}
-
-
-//-------------------------------------------------------------------------
-// OptionValueUUID
-//-------------------------------------------------------------------------
-void
-OptionValueUUID::DumpValue (Stream &strm)
-{
- m_uuid.Dump (&strm);
-}
-
-Error
-OptionValueUUID::SetValueFromCString (const char *value_cstr)
-{
- Error error;
- if (m_uuid.SetfromCString(value_cstr) == 0)
- error.SetErrorStringWithFormat ("invalid uuid string value '%s'", value_cstr);
- return error;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueFormat
-//-------------------------------------------------------------------------
-void
-OptionValueFormat::DumpValue (Stream &strm)
-{
- strm.PutCString (FormatManager::GetFormatAsCString (m_current_value));
-}
-
-Error
-OptionValueFormat::SetValueFromCString (const char *value_cstr)
-{
- Format new_format;
- Error error (Args::StringToFormat (value_cstr, new_format, NULL));
- if (error.Success())
- {
- m_value_was_set = true;
- m_current_value = new_format;
- }
- return error;
-}
-
-
-//-------------------------------------------------------------------------
-// OptionValueArray
-//-------------------------------------------------------------------------
-void
-OptionValueArray::DumpValue (Stream &strm)
-{
- const uint32_t size = m_values.size();
- for (uint32_t i = 0; i<size; ++i)
- {
- strm.Printf("[%u] ", i);
- m_values[i]->DumpValue (strm);
- }
-}
-
-Error
-OptionValueArray::SetValueFromCString (const char *value_cstr)
-{
- Error error;
- error.SetErrorStringWithFormat ("array option values don't yet support being set by string: '%s'", value_cstr);
- return error;
-}
-
-//-------------------------------------------------------------------------
-// OptionValueDictionary
-//-------------------------------------------------------------------------
-void
-OptionValueDictionary::DumpValue (Stream &strm)
-{
- collection::iterator pos, end = m_values.end();
-
- for (pos = m_values.begin(); pos != end; ++pos)
- {
- strm.Printf("%s=", pos->first.GetCString());
- pos->second->DumpValue (strm);
- }
-}
-
-Error
-OptionValueDictionary::SetValueFromCString (const char *value_cstr)
-{
- Error error;
- error.SetErrorStringWithFormat ("dictionary option values don't yet support being set by string: '%s'", value_cstr);
- return error;
-}
-
-lldb::OptionValueSP
-OptionValueDictionary::GetValueForKey (const ConstString &key) const
-{
- lldb::OptionValueSP value_sp;
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- value_sp = pos->second;
- return value_sp;
-}
-
-const char *
-OptionValueDictionary::GetStringValueForKey (const ConstString &key)
-{
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- if (pos->second->GetType() == OptionValue::eTypeString)
- return static_cast<OptionValueString *>(pos->second.get())->GetCurrentValue();
- }
- return NULL;
-}
-
-
-bool
-OptionValueDictionary::SetStringValueForKey (const ConstString &key,
- const char *value,
- bool can_replace)
-{
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- if (!can_replace)
- return false;
- if (pos->second->GetType() == OptionValue::eTypeString)
- {
- pos->second->SetValueFromCString(value);
- return true;
- }
- }
- m_values[key] = OptionValueSP (new OptionValueString (value));
- return true;
-
-}
-
-bool
-OptionValueDictionary::SetValueForKey (const ConstString &key,
- const lldb::OptionValueSP &value_sp,
- bool can_replace)
-{
- // Make sure the value_sp object is allowed to contain
- // values of the type passed in...
- if (value_sp && (m_type_mask & value_sp->GetTypeAsMask()))
- {
- if (!can_replace)
- {
- collection::const_iterator pos = m_values.find (key);
- if (pos != m_values.end())
- return false;
- }
- m_values[key] = value_sp;
- return true;
- }
- return false;
-}
-
-bool
-OptionValueDictionary::DeleteValueForKey (const ConstString &key)
-{
- collection::iterator pos = m_values.find (key);
- if (pos != m_values.end())
- {
- m_values.erase(pos);
- return true;
- }
- return false;
-}
-
-
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupArchitecture.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupArchitecture.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupArchitecture.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupArchitecture.cpp Thu Jun 6 19:06:43 2013
@@ -62,7 +62,7 @@ OptionGroupArchitecture::SetOptionValue
const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupBoolean.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupBoolean.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupBoolean.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupBoolean.cpp Thu Jun 6 19:06:43 2013
@@ -20,21 +20,20 @@ using namespace lldb_private;
OptionGroupBoolean::OptionGroupBoolean (uint32_t usage_mask,
bool required,
const char *long_option,
- char short_option,
- uint32_t completion_type,
- lldb::CommandArgumentType argument_type,
+ int short_option,
const char *usage_text,
- bool default_value) :
+ bool default_value,
+ bool no_argument_toggle_default) :
m_value (default_value, default_value)
{
m_option_definition.usage_mask = usage_mask;
m_option_definition.required = required;
m_option_definition.long_option = long_option;
m_option_definition.short_option = short_option;
- m_option_definition.option_has_arg = required_argument;
+ m_option_definition.option_has_arg = no_argument_toggle_default ? no_argument : required_argument;
m_option_definition.enum_values = NULL;
- m_option_definition.completion_type = completion_type;
- m_option_definition.argument_type = argument_type;
+ m_option_definition.completion_type = 0;
+ m_option_definition.argument_type = eArgTypeBoolean;
m_option_definition.usage_text = usage_text;
}
@@ -47,7 +46,17 @@ OptionGroupBoolean::SetOptionValue (Comm
uint32_t option_idx,
const char *option_arg)
{
- Error error (m_value.SetValueFromCString (option_arg));
+ Error error;
+ if (m_option_definition.option_has_arg == no_argument)
+ {
+ // Not argument, toggle the default value and mark the option as having been set
+ m_value.SetCurrentValue (!m_value.GetDefaultValue());
+ m_value.SetOptionWasSet ();
+ }
+ else
+ {
+ error = m_value.SetValueFromCString (option_arg);
+ }
return error;
}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFile.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFile.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFile.cpp Thu Jun 6 19:06:43 2013
@@ -20,7 +20,7 @@ using namespace lldb_private;
OptionGroupFile::OptionGroupFile (uint32_t usage_mask,
bool required,
const char *long_option,
- char short_option,
+ int short_option,
uint32_t completion_type,
lldb::CommandArgumentType argument_type,
const char *usage_text) :
@@ -43,8 +43,8 @@ OptionGroupFile::~OptionGroupFile ()
Error
OptionGroupFile::SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg)
+ uint32_t option_idx,
+ const char *option_arg)
{
Error error (m_file.SetValueFromCString (option_arg));
return error;
@@ -60,7 +60,7 @@ OptionGroupFile::OptionParsingStarting (
OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask,
bool required,
const char *long_option,
- char short_option,
+ int short_option,
uint32_t completion_type,
lldb::CommandArgumentType argument_type,
const char *usage_text) :
@@ -83,8 +83,8 @@ OptionGroupFileList::~OptionGroupFileLis
Error
OptionGroupFileList::SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg)
+ uint32_t option_idx,
+ const char *option_arg)
{
Error error (m_file_list.SetValueFromCString (option_arg));
return error;
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFormat.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFormat.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFormat.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupFormat.cpp Thu Jun 6 19:06:43 2013
@@ -7,12 +7,18 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/OptionGroupFormat.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
using namespace lldb;
@@ -67,7 +73,7 @@ OptionGroupFormat::SetOptionValue (Comma
const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
@@ -119,7 +125,7 @@ OptionGroupFormat::SetOptionValue (Comma
Format format = eFormatDefault;
uint32_t byte_size = 0;
- while (ParserGDBFormatLetter (gdb_format_cstr[0], format, byte_size))
+ while (ParserGDBFormatLetter (interpreter, gdb_format_cstr[0], format, byte_size))
{
++gdb_format_cstr;
}
@@ -139,7 +145,7 @@ OptionGroupFormat::SetOptionValue (Comma
// Anything that wasn't set correctly should be set to the
// previous default
if (format == eFormatInvalid)
- ParserGDBFormatLetter (m_prev_gdb_format, format, byte_size);
+ ParserGDBFormatLetter (interpreter, m_prev_gdb_format, format, byte_size);
const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
@@ -147,7 +153,7 @@ OptionGroupFormat::SetOptionValue (Comma
{
// Byte size is enabled
if (byte_size == 0)
- ParserGDBFormatLetter (m_prev_gdb_size, format, byte_size);
+ ParserGDBFormatLetter (interpreter, m_prev_gdb_size, format, byte_size);
}
else
{
@@ -161,9 +167,9 @@ OptionGroupFormat::SetOptionValue (Comma
if (count_enabled)
{
- // Count is enabled and was not set, set it to the default
+ // Count is enabled and was not set, set it to the default for gdb format statements (which is 1).
if (count == 0)
- count = m_count.GetDefaultValue();
+ count = 1;
}
else
{
@@ -199,8 +205,9 @@ OptionGroupFormat::SetOptionValue (Comma
}
bool
-OptionGroupFormat::ParserGDBFormatLetter (char format_letter, Format &format, uint32_t &byte_size)
+OptionGroupFormat::ParserGDBFormatLetter (CommandInterpreter &interpreter, char format_letter, Format &format, uint32_t &byte_size)
{
+ m_has_gdb_format = true;
switch (format_letter)
{
case 'o': format = eFormatOctal; m_prev_gdb_format = format_letter; return true;
@@ -209,7 +216,15 @@ OptionGroupFormat::ParserGDBFormatLetter
case 'u': format = eFormatUnsigned; m_prev_gdb_format = format_letter; return true;
case 't': format = eFormatBinary; m_prev_gdb_format = format_letter; return true;
case 'f': format = eFormatFloat; m_prev_gdb_format = format_letter; return true;
- case 'a': format = eFormatAddressInfo; m_prev_gdb_format = format_letter; return true;
+ case 'a': format = eFormatAddressInfo;
+ {
+ ExecutionContext exe_ctx(interpreter.GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ byte_size = target->GetArchitecture().GetAddressByteSize();
+ m_prev_gdb_format = format_letter;
+ return true;
+ }
case 'i': format = eFormatInstruction; m_prev_gdb_format = format_letter; return true;
case 'c': format = eFormatChar; m_prev_gdb_format = format_letter; return true;
case 's': format = eFormatCString; m_prev_gdb_format = format_letter; return true;
@@ -230,4 +245,5 @@ OptionGroupFormat::OptionParsingStarting
m_format.Clear();
m_byte_size.Clear();
m_count.Clear();
+ m_has_gdb_format = false;
}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupOutputFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupOutputFile.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupOutputFile.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupOutputFile.cpp Thu Jun 6 19:06:43 2013
@@ -31,8 +31,8 @@ OptionGroupOutputFile::~OptionGroupOutpu
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 , false, "outfile", 'o', required_argument, NULL, 0, eArgTypePath , "Specify a path for capturing command output."},
- { LLDB_OPT_SET_1 , false, "append-outfile" , 'A', no_argument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
+ { LLDB_OPT_SET_1 , false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename , "Specify a path for capturing command output."},
+ { LLDB_OPT_SET_1 , false, "append-outfile" , 'apnd', no_argument, NULL, 0, eArgTypeNone , "Append to the the file specified with '--outfile <path>'."},
};
uint32_t
@@ -49,11 +49,11 @@ OptionGroupOutputFile::GetDefinitions ()
Error
OptionGroupOutputFile::SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg)
+ uint32_t option_idx,
+ const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
@@ -61,7 +61,7 @@ OptionGroupOutputFile::SetOptionValue (C
error = m_file.SetValueFromCString (option_arg);
break;
- case 'A':
+ case 'apnd':
m_append.SetCurrentValue(true);
break;
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupPlatform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupPlatform.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupPlatform.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupPlatform.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/OptionGroupPlatform.h"
// C Includes
@@ -34,9 +36,11 @@ OptionGroupPlatform::CreatePlatformWithO
platform_sp = Platform::Create (m_platform_name.c_str(), error);
if (platform_sp)
{
- if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, &platform_arch))
+ if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch))
{
- error.SetErrorStringWithFormat("platform '%s' doesn't support '%s'", platform_sp->GetName(), arch.GetTriple().getTriple().c_str());
+ error.SetErrorStringWithFormat ("platform '%s' doesn't support '%s'",
+ platform_sp->GetName().GetCString(),
+ arch.GetTriple().getTriple().c_str());
platform_sp.reset();
return platform_sp;
}
@@ -84,7 +88,7 @@ g_option_table[] =
{ LLDB_OPT_SET_ALL, false, "platform", 'p', required_argument, NULL, 0, eArgTypePlatform, "Specify name of the platform to use for this target, creating the platform if necessary."},
{ LLDB_OPT_SET_ALL, false, "version" , 'v', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK version to use prior to connecting." },
{ LLDB_OPT_SET_ALL, false, "build" , 'b', required_argument, NULL, 0, eArgTypeNone, "Specify the initial SDK build number." },
- { LLDB_OPT_SET_ALL, false, "sysroot" , 's', required_argument, NULL, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
+ { LLDB_OPT_SET_ALL, false, "sysroot" , 'S', required_argument, NULL, 0, eArgTypeFilename, "Specify the SDK root directory that contains a root of all remote system files." }
};
const OptionDefinition*
@@ -113,7 +117,7 @@ OptionGroupPlatform::SetOptionValue (Com
if (!m_include_platform_option)
++option_idx;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
@@ -133,7 +137,7 @@ OptionGroupPlatform::SetOptionValue (Com
m_sdk_build.SetCString (option_arg);
break;
- case 's':
+ case 'S':
m_sdk_sysroot.SetCString (option_arg);
break;
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUInt64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUInt64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUInt64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUInt64.cpp Thu Jun 6 19:06:43 2013
@@ -20,7 +20,7 @@ using namespace lldb_private;
OptionGroupUInt64::OptionGroupUInt64 (uint32_t usage_mask,
bool required,
const char *long_option,
- char short_option,
+ int short_option,
uint32_t completion_type,
lldb::CommandArgumentType argument_type,
const char *usage_text,
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUUID.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUUID.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUUID.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupUUID.cpp Thu Jun 6 19:06:43 2013
@@ -47,11 +47,11 @@ OptionGroupUUID::GetDefinitions ()
Error
OptionGroupUUID::SetOptionValue (CommandInterpreter &interpreter,
- uint32_t option_idx,
- const char *option_arg)
+ uint32_t option_idx,
+ const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupValueObjectDisplay.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupValueObjectDisplay.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupValueObjectDisplay.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupValueObjectDisplay.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
// C Includes
@@ -31,19 +33,18 @@ OptionGroupValueObjectDisplay::~OptionGr
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1, false, "dynamic-type", 'd', required_argument, TargetInstanceSettings::g_dynamic_value_types,
- 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
- { LLDB_OPT_SET_1, false, "synthetic-type", 'S', required_argument, NULL, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
- { LLDB_OPT_SET_1, false, "depth", 'D', required_argument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
- { LLDB_OPT_SET_1, false, "flat", 'F', no_argument, NULL, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
- { LLDB_OPT_SET_1, false, "location", 'L', no_argument, NULL, 0, eArgTypeNone, "Show variable location information."},
- { LLDB_OPT_SET_1, false, "objc", 'O', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
- { LLDB_OPT_SET_1, false, "ptr-depth", 'P', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
- { LLDB_OPT_SET_1, false, "show-types", 'T', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
- { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', optional_argument, NULL, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
- { LLDB_OPT_SET_1, false, "raw-output", 'R', no_argument, NULL, 0, eArgTypeNone, "Don't use formatting options."},
- { LLDB_OPT_SET_1, false, "show-all-children",'A', no_argument, NULL, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
- { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
+ { LLDB_OPT_SET_1, false, "dynamic-type", 'd', required_argument, g_dynamic_value_types, 0, eArgTypeNone, "Show the object as its full dynamic type, not its static type, if available."},
+ { LLDB_OPT_SET_1, false, "synthetic-type", 'S', required_argument, NULL, 0, eArgTypeBoolean, "Show the object obeying its synthetic provider, if available."},
+ { LLDB_OPT_SET_1, false, "depth", 'D', required_argument, NULL, 0, eArgTypeCount, "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+ { LLDB_OPT_SET_1, false, "flat", 'F', no_argument, NULL, 0, eArgTypeNone, "Display results in a flat format that uses expression paths for each variable or member."},
+ { LLDB_OPT_SET_1, false, "location", 'L', no_argument, NULL, 0, eArgTypeNone, "Show variable location information."},
+ { LLDB_OPT_SET_1, false, "object-description", 'O', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."},
+ { LLDB_OPT_SET_1, false, "ptr-depth", 'P', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."},
+ { LLDB_OPT_SET_1, false, "show-types", 'T', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."},
+ { LLDB_OPT_SET_1, false, "no-summary-depth", 'Y', optional_argument, NULL, 0, eArgTypeCount, "Set the depth at which omitting summary information stops (default is 1)."},
+ { LLDB_OPT_SET_1, false, "raw-output", 'R', no_argument, NULL, 0, eArgTypeNone, "Don't use formatting options."},
+ { LLDB_OPT_SET_1, false, "show-all-children", 'A', no_argument, NULL, 0, eArgTypeNone, "Ignore the upper bound on the number of children to show."},
+ { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
uint32_t
@@ -65,7 +66,7 @@ OptionGroupValueObjectDisplay::SetOption
const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
bool success = false;
switch (short_option)
@@ -73,7 +74,7 @@ OptionGroupValueObjectDisplay::SetOption
case 'd':
{
int32_t result;
- result = Args::StringToOptionEnum (option_arg, TargetInstanceSettings::g_dynamic_value_types, 2, error);
+ result = Args::StringToOptionEnum (option_arg, g_dynamic_value_types, 2, error);
if (error.Success())
use_dynamic = (lldb::DynamicValueType) result;
}
@@ -145,3 +146,36 @@ OptionGroupValueObjectDisplay::OptionPar
use_dynamic = lldb::eNoDynamicValues;
}
}
+
+ValueObject::DumpValueObjectOptions
+OptionGroupValueObjectDisplay::GetAsDumpOptions (bool objc_is_compact,
+ lldb::Format format,
+ lldb::TypeSummaryImplSP summary_sp)
+{
+ ValueObject::DumpValueObjectOptions options;
+ options.SetMaximumPointerDepth(ptr_depth);
+ if (use_objc)
+ options.SetShowSummary(false);
+ else
+ options.SetOmitSummaryDepth(no_summary_depth);
+ options.SetMaximumDepth(max_depth)
+ .SetShowTypes(show_types)
+ .SetShowLocation(show_location)
+ .SetUseObjectiveC(use_objc)
+ .SetUseDynamicType(use_dynamic)
+ .SetUseSyntheticValue(use_synth)
+ .SetFlatOutput(flat_output)
+ .SetIgnoreCap(ignore_cap)
+ .SetFormat(format)
+ .SetSummary(summary_sp);
+
+ if (objc_is_compact)
+ options.SetHideRootType(use_objc)
+ .SetHideName(use_objc)
+ .SetHideValue(use_objc);
+
+ if (be_raw)
+ options.SetRawDisplay(true);
+
+ return options;
+}
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupVariable.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupVariable.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupVariable.cpp Thu Jun 6 19:06:43 2013
@@ -7,14 +7,18 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/OptionGroupVariable.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/Target/Target.h"
+#include "lldb/Core/Error.h"
+#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
using namespace lldb;
@@ -24,20 +28,40 @@ using namespace lldb_private;
static OptionDefinition
g_option_table[] =
{
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', no_argument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
- { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."},
- { LLDB_OPT_SET_2, false, "summary-string", 'z', required_argument, NULL, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g', no_argument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."},
+ { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."},
+ { LLDB_OPT_SET_2, false, "summary-string", 'z', required_argument, NULL, 0, eArgTypeName, "Specify a summary string to use to format the variable output."},
};
+static Error
+ValidateNamedSummary (const char* str, void*)
+{
+ if (!str || !str[0])
+ return Error("must specify a valid named summary");
+ TypeSummaryImplSP summary_sp;
+ if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(ConstString(str), summary_sp) == false)
+ return Error("must specify a valid named summary");
+ return Error();
+}
+
+static Error
+ValidateSummaryString (const char* str, void*)
+{
+ if (!str || !str[0])
+ return Error("must specify a non-empty summary string");
+ return Error();
+}
OptionGroupVariable::OptionGroupVariable (bool show_frame_options) :
OptionGroup(),
- include_frame_options (show_frame_options)
+ include_frame_options (show_frame_options),
+ summary(ValidateNamedSummary),
+ summary_string(ValidateSummaryString)
{
}
@@ -53,7 +77,7 @@ OptionGroupVariable::SetOptionValue (Com
Error error;
if (!include_frame_options)
option_idx += 3;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
case 'r': use_regex = true; break;
@@ -65,10 +89,10 @@ OptionGroupVariable::SetOptionValue (Com
show_scope = true;
break;
case 'y':
- summary.SetCurrentValue(option_arg);
+ error = summary.SetCurrentValue(option_arg);
break;
case 'z':
- summary_string.SetCurrentValue(option_arg);
+ error = summary_string.SetCurrentValue(option_arg);
break;
default:
error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Modified: lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupWatchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupWatchpoint.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupWatchpoint.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/OptionGroupWatchpoint.cpp Thu Jun 6 19:06:43 2013
@@ -73,7 +73,7 @@ OptionGroupWatchpoint::SetOptionValue (C
const char *option_arg)
{
Error error;
- char short_option = (char) g_option_table[option_idx].short_option;
+ const int short_option = g_option_table[option_idx].short_option;
switch (short_option)
{
case 'w':
Modified: lldb/branches/lldb-platform-work/source/Interpreter/Options.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/Options.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/Options.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/Options.cpp Thu Jun 6 19:06:43 2013
@@ -7,13 +7,15 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/Options.h"
// C Includes
// C++ Includes
#include <algorithm>
#include <bitset>
-#include <set>
+#include <map>
// Other libraries and framework includes
// Project includes
@@ -58,7 +60,7 @@ Options::NotifyOptionParsingFinished ()
void
Options::OptionSeen (int option_idx)
{
- m_seen_options.insert ((char) option_idx);
+ m_seen_options.insert (option_idx);
}
// Returns true is set_a is a subset of set_b; Otherwise returns false.
@@ -266,33 +268,54 @@ Options::GetLongOptions ()
return NULL;
uint32_t i;
- uint32_t j;
const OptionDefinition *opt_defs = GetDefinitions();
- std::bitset<256> option_seen;
+ std::map<int, uint32_t> option_seen;
m_getopt_table.resize(num_options + 1);
- for (i = 0, j = 0; i < num_options; ++i)
+ for (i = 0; i < num_options; ++i)
{
- char short_opt = opt_defs[i].short_option;
+ const int short_opt = opt_defs[i].short_option;
- if (option_seen.test(short_opt) == false)
- {
- m_getopt_table[j].name = opt_defs[i].long_option;
- m_getopt_table[j].has_arg = opt_defs[i].option_has_arg;
- m_getopt_table[j].flag = NULL;
- m_getopt_table[j].val = opt_defs[i].short_option;
- option_seen.set(short_opt);
- ++j;
+ m_getopt_table[i].name = opt_defs[i].long_option;
+ m_getopt_table[i].has_arg = opt_defs[i].option_has_arg;
+ m_getopt_table[i].flag = NULL;
+ m_getopt_table[i].val = short_opt;
+
+ if (option_seen.find(short_opt) == option_seen.end())
+ {
+ option_seen[short_opt] = i;
+ }
+ else if (short_opt)
+ {
+ m_getopt_table[i].val = 0;
+ std::map<int, uint32_t>::const_iterator pos = option_seen.find(short_opt);
+ StreamString strm;
+ if (isprint8(short_opt))
+ Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option -%c that conflicts with option[%u] --%s, short option won't be used for --%s\n",
+ i,
+ opt_defs[i].long_option,
+ short_opt,
+ pos->second,
+ m_getopt_table[pos->second].name,
+ opt_defs[i].long_option);
+ else
+ Host::SystemLog (Host::eSystemLogError, "option[%u] --%s has a short option 0x%x that conflicts with option[%u] --%s, short option won't be used for --%s\n",
+ i,
+ opt_defs[i].long_option,
+ short_opt,
+ pos->second,
+ m_getopt_table[pos->second].name,
+ opt_defs[i].long_option);
}
}
- //getopt_long requires a NULL final entry in the table:
-
- m_getopt_table[j].name = NULL;
- m_getopt_table[j].has_arg = 0;
- m_getopt_table[j].flag = NULL;
- m_getopt_table[j].val = 0;
+ //getopt_long_only requires a NULL final entry in the table:
+
+ m_getopt_table[i].name = NULL;
+ m_getopt_table[i].has_arg = 0;
+ m_getopt_table[i].flag = NULL;
+ m_getopt_table[i].val = 0;
}
if (m_getopt_table.empty())
@@ -389,6 +412,57 @@ Options::SupportsLongOption (const char
return false;
}
+enum OptionDisplayType
+{
+ eDisplayBestOption,
+ eDisplayShortOption,
+ eDisplayLongOption
+};
+
+static bool
+PrintOption (const OptionDefinition &opt_def,
+ OptionDisplayType display_type,
+ const char *header,
+ const char *footer,
+ bool show_optional,
+ Stream &strm)
+{
+ const bool has_short_option = isprint8(opt_def.short_option) != 0;
+
+ if (display_type == eDisplayShortOption && !has_short_option)
+ return false;
+
+ if (header && header[0])
+ strm.PutCString(header);
+
+ if (show_optional && !opt_def.required)
+ strm.PutChar('[');
+ const bool show_short_option = has_short_option && display_type != eDisplayLongOption;
+ if (show_short_option)
+ strm.Printf ("-%c", opt_def.short_option);
+ else
+ strm.Printf ("--%s", opt_def.long_option);
+ switch (opt_def.option_has_arg)
+ {
+ case no_argument:
+ break;
+ case required_argument:
+ strm.Printf (" <%s>", CommandObject::GetArgumentName (opt_def.argument_type));
+ break;
+
+ case optional_argument:
+ strm.Printf ("%s[<%s>]",
+ show_short_option ? "" : "=",
+ CommandObject::GetArgumentName (opt_def.argument_type));
+ break;
+ }
+ if (show_optional && !opt_def.required)
+ strm.PutChar(']');
+ if (footer && footer[0])
+ strm.PutCString(footer);
+ return true;
+}
+
void
Options::GenerateOptionUsage
(
@@ -439,18 +513,18 @@ Options::GenerateOptionUsage
// Different option sets may require different args.
StreamString args_str;
- cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
+ if (cmd)
+ cmd->GetFormattedCommandArguments(args_str, opt_set_mask);
// First go through and print all options that take no arguments as
// a single string. If a command has "-a" "-b" and "-c", this will show
// up as [-abc]
- std::set<char> options;
- std::set<char>::const_iterator options_pos, options_end;
- bool first;
- for (i = 0, first = true; i < num_options; ++i)
+ std::set<int> options;
+ std::set<int>::const_iterator options_pos, options_end;
+ for (i = 0; i < num_options; ++i)
{
- if (opt_defs[i].usage_mask & opt_set_mask)
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
// Add current option to the end of out_stream.
@@ -471,17 +545,17 @@ Options::GenerateOptionUsage
options_pos != options_end;
++options_pos)
{
- if (i==0 && ::isupper (*options_pos))
+ if (i==0 && ::islower (*options_pos))
continue;
- if (i==1 && ::islower (*options_pos))
+ if (i==1 && ::isupper (*options_pos))
continue;
- strm << *options_pos;
+ strm << (char)*options_pos;
}
}
for (i = 0, options.clear(); i < num_options; ++i)
{
- if (opt_defs[i].usage_mask & opt_set_mask)
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
// Add current option to the end of out_stream.
@@ -502,11 +576,11 @@ Options::GenerateOptionUsage
options_pos != options_end;
++options_pos)
{
- if (i==0 && ::isupper (*options_pos))
+ if (i==0 && ::islower (*options_pos))
continue;
- if (i==1 && ::islower (*options_pos))
+ if (i==1 && ::isupper (*options_pos))
continue;
- strm << *options_pos;
+ strm << (char)*options_pos;
}
strm.PutChar(']');
}
@@ -515,26 +589,10 @@ Options::GenerateOptionUsage
for (i = 0; i < num_options; ++i)
{
- if (opt_defs[i].usage_mask & opt_set_mask)
+ if (opt_defs[i].usage_mask & opt_set_mask && isprint8(opt_defs[i].short_option))
{
- // Add current option to the end of out_stream.
- CommandArgumentType arg_type = opt_defs[i].argument_type;
-
- if (opt_defs[i].required)
- {
- if (opt_defs[i].option_has_arg == required_argument)
- {
- strm.Printf (" -%c <%s>",
- opt_defs[i].short_option,
- CommandObject::GetArgumentName (arg_type));
- }
- else if (opt_defs[i].option_has_arg == optional_argument)
- {
- strm.Printf (" -%c [<%s>]",
- opt_defs[i].short_option,
- CommandObject::GetArgumentName (arg_type));
- }
- }
+ if (opt_defs[i].required && opt_defs[i].option_has_arg != no_argument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
}
}
@@ -546,17 +604,8 @@ Options::GenerateOptionUsage
{
// Add current option to the end of out_stream.
- CommandArgumentType arg_type = opt_defs[i].argument_type;
-
- if (! opt_defs[i].required)
- {
- if (opt_defs[i].option_has_arg == required_argument)
- strm.Printf (" [-%c <%s>]", opt_defs[i].short_option,
- CommandObject::GetArgumentName (arg_type));
- else if (opt_defs[i].option_has_arg == optional_argument)
- strm.Printf (" [-%c [<%s>]]", opt_defs[i].short_option,
- CommandObject::GetArgumentName (arg_type));
- }
+ if (!opt_defs[i].required && opt_defs[i].option_has_arg != no_argument)
+ PrintOption (opt_defs[i], eDisplayBestOption, " ", NULL, true, strm);
}
}
@@ -569,7 +618,8 @@ Options::GenerateOptionUsage
}
}
- if (cmd->WantsRawCommandString() &&
+ if (cmd &&
+ cmd->WantsRawCommandString() &&
arguments_str.GetSize() > 0)
{
strm.PutChar('\n');
@@ -586,86 +636,69 @@ Options::GenerateOptionUsage
// This variable is used to keep track of which options' info we've printed out, because some options can be in
// more than one usage level, but we only want to print the long form of its information once.
- OptionSet options_seen;
- OptionSet::iterator pos;
+ std::multimap<int, uint32_t> options_seen;
strm.IndentMore (5);
- std::vector<char> sorted_options;
-
-
// Put the unique command options in a vector & sort it, so we can output them alphabetically (by short_option)
// when writing out detailed help for each option.
for (i = 0; i < num_options; ++i)
- {
- pos = options_seen.find (opt_defs[i].short_option);
- if (pos == options_seen.end())
- {
- options_seen.insert (opt_defs[i].short_option);
- sorted_options.push_back (opt_defs[i].short_option);
- }
- }
-
- std::sort (sorted_options.begin(), sorted_options.end());
+ options_seen.insert(std::make_pair(opt_defs[i].short_option, i));
// Go through the unique'd and alphabetically sorted vector of options, find the table entry for each option
// and write out the detailed help information for that option.
- int first_option_printed = 1;
- size_t end = sorted_options.size();
- for (size_t j = 0; j < end; ++j)
- {
- char option = sorted_options[j];
- bool found = false;
- for (i = 0; i < num_options && !found; ++i)
- {
- if (opt_defs[i].short_option == option)
- {
- found = true;
- //Print out the help information for this option.
-
- // Put a newline separation between arguments
- if (first_option_printed)
- first_option_printed = 0;
- else
- strm.EOL();
-
- CommandArgumentType arg_type = opt_defs[i].argument_type;
-
- StreamString arg_name_str;
- arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
+ bool first_option_printed = false;;
- strm.Indent ();
- strm.Printf ("-%c", opt_defs[i].short_option);
- if (arg_type != eArgTypeNone)
- strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
- strm.Printf (" ( --%s", opt_defs[i].long_option);
- if (arg_type != eArgTypeNone)
- strm.Printf (" <%s>", CommandObject::GetArgumentName (arg_type));
- strm.PutCString(" )\n");
-
- strm.IndentMore (5);
-
- if (opt_defs[i].usage_text)
- OutputFormattedUsageText (strm,
- opt_defs[i].usage_text,
- screen_width);
- if (opt_defs[i].enum_values != NULL)
- {
- strm.Indent ();
- strm.Printf("Values: ");
- for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++)
- {
- if (k == 0)
- strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
- else
- strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
- }
- strm.EOL();
- }
- strm.IndentLess (5);
+ for (auto pos : options_seen)
+ {
+ i = pos.second;
+ //Print out the help information for this option.
+
+ // Put a newline separation between arguments
+ if (first_option_printed)
+ strm.EOL();
+ else
+ first_option_printed = true;
+
+ CommandArgumentType arg_type = opt_defs[i].argument_type;
+
+ StreamString arg_name_str;
+ arg_name_str.Printf ("<%s>", CommandObject::GetArgumentName (arg_type));
+
+ strm.Indent ();
+ if (opt_defs[i].short_option && isprint8(opt_defs[i].short_option))
+ {
+ PrintOption (opt_defs[i], eDisplayShortOption, NULL, NULL, false, strm);
+ PrintOption (opt_defs[i], eDisplayLongOption, " ( ", " )", false, strm);
+ }
+ else
+ {
+ // Short option is not printable, just print long option
+ PrintOption (opt_defs[i], eDisplayLongOption, NULL, NULL, false, strm);
+ }
+ strm.EOL();
+
+ strm.IndentMore (5);
+
+ if (opt_defs[i].usage_text)
+ OutputFormattedUsageText (strm,
+ opt_defs[i].usage_text,
+ screen_width);
+ if (opt_defs[i].enum_values != NULL)
+ {
+ strm.Indent ();
+ strm.Printf("Values: ");
+ for (int k = 0; opt_defs[i].enum_values[k].string_value != NULL; k++)
+ {
+ if (k == 0)
+ strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
+ else
+ strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
}
+ strm.EOL();
}
+ strm.IndentLess (5);
}
// Restore the indent level
@@ -762,7 +795,7 @@ Options::HandleOptionCompletion
}
else if (opt_defs_index != OptionArgElement::eUnrecognizedArg)
{
- // We recognized it, if it an incomplete long option, complete it anyway (getopt_long is
+ // We recognized it, if it an incomplete long option, complete it anyway (getopt_long_only is
// happy with shortest unique string, but it's still a nice thing to do.) Otherwise return
// The string so the upper level code will know this is a full match and add the " ".
if (cur_opt_str && strlen (cur_opt_str) > 2
@@ -785,7 +818,7 @@ Options::HandleOptionCompletion
// FIXME - not handling wrong options yet:
// Check to see if they are writing a long option & complete it.
// I think we will only get in here if the long option table has two elements
- // that are not unique up to this point. getopt_long does shortest unique match
+ // that are not unique up to this point. getopt_long_only does shortest unique match
// for long options already.
if (cur_opt_str && strlen (cur_opt_str) > 2
@@ -867,7 +900,7 @@ Options::HandleOptionArgumentCompletion
)
{
const OptionDefinition *opt_defs = GetDefinitions();
- std::auto_ptr<SearchFilter> filter_ap;
+ std::unique_ptr<SearchFilter> filter_ap;
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
Copied: lldb/branches/lldb-platform-work/source/Interpreter/PythonDataObjects.cpp (from r182522, lldb/trunk/source/Interpreter/PythonDataObjects.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/PythonDataObjects.cpp?p2=lldb/branches/lldb-platform-work/source/Interpreter/PythonDataObjects.cpp&p1=lldb/trunk/source/Interpreter/PythonDataObjects.cpp&r1=182522&r2=183468&rev=183468&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/PythonDataObjects.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/PythonDataObjects.cpp Thu Jun 6 19:06:43 2013
@@ -21,6 +21,10 @@
#include <Python.h>
#endif
+#include <stdio.h>
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/File.h"
#include "lldb/Interpreter/PythonDataObjects.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
@@ -37,6 +41,31 @@ PythonObject::PythonObject (const lldb::
Reset ((PyObject *)script_object_sp->GetObject());
}
+void
+PythonObject::Dump (Stream &strm) const
+{
+ if (m_py_obj)
+ {
+ FILE *file = ::tmpfile();
+ if (file)
+ {
+ ::PyObject_Print (m_py_obj, file, 0);
+ const long length = ftell (file);
+ if (length)
+ {
+ ::rewind(file);
+ std::vector<char> file_contents (length,'\0');
+ const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
+ if (length_read > 0)
+ strm.Write (file_contents.data(), length_read);
+ }
+ ::fclose (file);
+ }
+ }
+ else
+ strm.PutCString ("NULL");
+}
+
//----------------------------------------------------------------------
// PythonString
//----------------------------------------------------------------------
Modified: lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreter.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreter.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreter.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/ScriptInterpreter.h"
#include <string>
@@ -79,6 +81,12 @@ ScriptInterpreter::LanguageToString (lld
return return_value;
}
+std::unique_ptr<ScriptInterpreterLocker>
+ScriptInterpreter::AcquireInterpreterLock ()
+{
+ return std::unique_ptr<ScriptInterpreterLocker>(new ScriptInterpreterLocker());
+}
+
void
ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback)
{
Modified: lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterNone.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterNone.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterNone.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterNone.cpp Thu Jun 6 19:06:43 2013
@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Interpreter/ScriptInterpreterNone.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
@@ -26,7 +28,7 @@ ScriptInterpreterNone::~ScriptInterprete
}
bool
-ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, bool enable_io)
+ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&)
{
m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
return false;
Modified: lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Interpreter/ScriptInterpreterPython.cpp Thu Jun 6 19:06:43 2013
@@ -52,9 +52,12 @@ static ScriptInterpreter::SWIGPythonCalc
static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
+static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = NULL;
static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
+static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = NULL;
static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
+static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL;
// these are the Pythonic implementations of the required callbacks
// these are scripting-language specific, which is why they belong here
@@ -62,169 +65,124 @@ static ScriptInterpreter::SWIGPythonCall
// on linkage-time resolution because the SWIG stuff and this file
// get built at different times
extern "C" bool
-LLDBSwigPythonBreakpointCallbackFunction
-(
- const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& sb_frame,
- const lldb::BreakpointLocationSP& sb_bp_loc
- );
+LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::BreakpointLocationSP& sb_bp_loc);
extern "C" bool
-LLDBSwigPythonWatchpointCallbackFunction
-(
- const char *python_function_name,
- const char *session_dictionary_name,
- const lldb::StackFrameSP& sb_frame,
- const lldb::WatchpointSP& sb_wp
- );
+LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& sb_frame,
+ const lldb::WatchpointSP& sb_wp);
extern "C" bool
-LLDBSwigPythonCallTypeScript
-(
- const char *python_function_name,
- void *session_dictionary,
- const lldb::ValueObjectSP& valobj_sp,
- void** pyfunct_wrapper,
- std::string& retval
- );
+LLDBSwigPythonCallTypeScript (const char *python_function_name,
+ void *session_dictionary,
+ const lldb::ValueObjectSP& valobj_sp,
+ void** pyfunct_wrapper,
+ std::string& retval);
extern "C" void*
-LLDBSwigPythonCreateSyntheticProvider
-(
- const std::string python_class_name,
- const char *session_dictionary_name,
- const lldb::ValueObjectSP& valobj_sp
- );
+LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ValueObjectSP& valobj_sp);
-extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor);
-extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
-extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
-extern "C" void* LLDBSWIGPython_CastPyObjectToSBValue (void* data);
-extern "C" bool LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
+extern "C" uint32_t
+LLDBSwigPython_CalculateNumChildren (void *implementor);
-extern "C" bool LLDBSwigPythonCallCommand
-(
- const char *python_function_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger,
- const char* args,
- std::string& err_msg,
- lldb_private::CommandReturnObject& cmd_retobj
- );
+extern "C" void *
+LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx);
-extern "C" bool LLDBSwigPythonCallModuleInit
-(
- const std::string python_module_name,
- const char *session_dictionary_name,
- lldb::DebuggerSP& debugger
- );
+extern "C" int
+LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name);
-static int
-_check_and_flush (FILE *stream)
-{
- int prev_fail = ferror (stream);
- return fflush (stream) || prev_fail ? EOF : 0;
-}
+extern "C" void *
+LLDBSWIGPython_CastPyObjectToSBValue (void* data);
-static Predicate<lldb::tid_t> &
-PythonMutexPredicate ()
-{
- static lldb_private::Predicate<lldb::tid_t> g_interpreter_is_running (LLDB_INVALID_THREAD_ID);
- return g_interpreter_is_running;
-}
+extern lldb::ValueObjectSP
+LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data);
-bool
-ScriptInterpreterPython::Locker::CurrentThreadHasPythonLock ()
-{
- TimeValue timeout;
+extern "C" bool
+LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
- timeout = TimeValue::Now(); // Don't wait any time.
+extern "C" bool
+LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);
- return PythonMutexPredicate().WaitForValueEqualTo (Host::GetCurrentThreadID(), &timeout, NULL);
-}
+extern "C" bool
+LLDBSwigPythonCallCommand (const char *python_function_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ std::string& err_msg,
+ lldb_private::CommandReturnObject& cmd_retobj);
-bool
-ScriptInterpreterPython::Locker::TryGetPythonLock (uint32_t seconds_to_wait)
-{
-
- TimeValue timeout;
-
- if (seconds_to_wait != UINT32_MAX)
- {
- timeout = TimeValue::Now();
- timeout.OffsetWithSeconds (seconds_to_wait);
- }
-
- return PythonMutexPredicate().WaitForValueEqualToAndSetValueTo (LLDB_INVALID_THREAD_ID,
- Host::GetCurrentThreadID(), &timeout, NULL);
-}
+extern "C" bool
+LLDBSwigPythonCallModuleInit (const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger);
-void
-ScriptInterpreterPython::Locker::ReleasePythonLock ()
+extern "C" void*
+LLDBSWIGPythonCreateOSPlugin (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP& process_sp);
+
+static int
+_check_and_flush (FILE *stream)
{
- PythonMutexPredicate().SetValue (LLDB_INVALID_THREAD_ID, eBroadcastAlways);
+ int prev_fail = ferror (stream);
+ return fflush (stream) || prev_fail ? EOF : 0;
}
ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
uint16_t on_entry,
uint16_t on_leave,
FILE* wait_msg_handle) :
- m_need_session( (on_leave & TearDownSession) == TearDownSession ),
- m_release_lock ( false ), // decide in constructor body
+ ScriptInterpreterLocker (),
+ m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
m_python_interpreter(py_interpreter),
m_tmp_fh(wait_msg_handle)
{
if (m_python_interpreter && !m_tmp_fh)
m_tmp_fh = (m_python_interpreter->m_dbg_stdout ? m_python_interpreter->m_dbg_stdout : stdout);
-
- if ( (on_entry & AcquireLock) == AcquireLock )
+
+ DoAcquireLock();
+ if ((on_entry & InitSession) == InitSession)
{
- if (CurrentThreadHasPythonLock())
+ if (DoInitSession((on_entry & InitGlobals) == InitGlobals) == false)
{
- if ( (on_leave & FreeLock) == FreeLock )
- m_release_lock = true;
- }
- else
- {
- DoAcquireLock();
- if ( (on_leave & FreeLock) == FreeLock )
- m_release_lock = true;
- if ( (on_leave & FreeAcquiredLock) == FreeAcquiredLock )
- m_release_lock = true;
+ // Don't teardown the session if we didn't init it.
+ m_teardown_session = false;
}
}
- if ( (on_entry & InitSession) == InitSession )
- DoInitSession();
}
bool
ScriptInterpreterPython::Locker::DoAcquireLock()
{
- if (!CurrentThreadHasPythonLock())
- {
- while (!TryGetPythonLock (1))
- if (m_tmp_fh)
- fprintf (m_tmp_fh,
- "Python interpreter locked on another thread; waiting to acquire lock...\n");
- }
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ m_GILState = PyGILState_Ensure();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
return true;
}
bool
-ScriptInterpreterPython::Locker::DoInitSession()
+ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals)
{
if (!m_python_interpreter)
return false;
- m_python_interpreter->EnterSession ();
- return true;
+ return m_python_interpreter->EnterSession (init_lldb_globals);
}
bool
ScriptInterpreterPython::Locker::DoFreeLock()
{
- ReleasePythonLock ();
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release(m_GILState);
return true;
}
@@ -239,30 +197,11 @@ ScriptInterpreterPython::Locker::DoTearD
ScriptInterpreterPython::Locker::~Locker()
{
- if (m_need_session)
+ if (m_teardown_session)
DoTearDownSession();
- if (m_release_lock)
- DoFreeLock();
+ DoFreeLock();
}
-class ForceDisableSyntheticChildren
-{
-public:
- ForceDisableSyntheticChildren (Target* target) :
- m_target(target)
- {
- m_old_value = target->GetSuppressSyntheticValue();
- target->SetSuppressSyntheticValue(true);
- }
- ~ForceDisableSyntheticChildren ()
- {
- m_target->SetSuppressSyntheticValue(m_old_value);
- }
-private:
- Target* m_target;
- bool m_old_value;
-};
-
ScriptInterpreterPython::PythonInputReaderManager::PythonInputReaderManager (ScriptInterpreterPython *interpreter) :
m_interpreter(interpreter),
m_debugger_sp(),
@@ -308,37 +247,31 @@ m_error(false)
ScriptInterpreterPython::PythonInputReaderManager::~PythonInputReaderManager()
{
- if (m_interpreter)
- {
- if (m_interpreter->m_embedded_thread_input_reader_sp)
- m_interpreter->m_embedded_thread_input_reader_sp->SetIsDone (true);
- m_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
- }
-
-
- if (m_reader_sp)
+ // Nothing to do if either m_interpreter or m_reader_sp is invalid.
+ if (!m_interpreter || !m_reader_sp)
+ return;
+
+ m_reader_sp->SetIsDone (true);
+ if (m_debugger_sp)
+ m_debugger_sp->PopInputReader(m_reader_sp);
+
+ // Only mess with m_interpreter's counterpart if, indeed, they are the same object.
+ if (m_reader_sp.get() == m_interpreter->m_embedded_thread_input_reader_sp.get())
{
- m_reader_sp->SetIsDone (true);
- if (m_debugger_sp)
- m_debugger_sp->PopInputReader(m_reader_sp);
- }
-
- if (m_interpreter)
+ m_interpreter->m_embedded_thread_pty.CloseSlaveFileDescriptor();
m_interpreter->m_embedded_thread_input_reader_sp.reset();
+ }
}
size_t
-ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback
-(
- void *baton,
- InputReader &reader,
- InputReaderAction notification,
- const char *bytes,
- size_t bytes_len
- )
+ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *baton,
+ InputReader &reader,
+ InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len)
{
lldb::thread_t embedded_interpreter_thread;
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (baton == NULL)
return 0;
@@ -348,8 +281,6 @@ ScriptInterpreterPython::PythonInputRead
if (script_interpreter->m_script_lang != eScriptLanguagePython)
return 0;
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
-
switch (notification)
{
case eInputReaderActivate:
@@ -360,26 +291,23 @@ ScriptInterpreterPython::PythonInputRead
input_fd = STDIN_FILENO;
script_interpreter->SaveTerminalState(input_fd);
-
- {
- ScriptInterpreterPython::Locker locker(script_interpreter,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
- ScriptInterpreterPython::Locker::FreeAcquiredLock);
- }
-
+
char error_str[1024];
- if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
+ if (script_interpreter->m_embedded_thread_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
sizeof(error_str)))
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
- script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor());
+ script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor());
{
StreamString run_string;
char error_str[1024];
- const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
+ const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
{
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
@@ -404,7 +332,7 @@ ScriptInterpreterPython::PythonInputRead
if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
{
if (log)
- log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", embedded_interpreter_thread);
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
Error detach_error;
Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
}
@@ -430,29 +358,33 @@ ScriptInterpreterPython::PythonInputRead
break;
case eInputReaderReactivate:
- {
- // Don't try and acquire the interpreter lock here because code like
- // this:
- //
- // (lldb) script
- // >>> v = lldb.frame.EvaluateExpression("collection->get_at_index(12)")
- //
- // This will cause the process to run. The interpreter lock is taken
- // by the input reader for the "script" command. If we try and acquire
- // the lock here, when the process runs it might deactivate this input
- // reader (if STDIN is hooked up to the inferior process) and
- // reactivate it when the process stops which will deadlock.
- //ScriptInterpreterPython::Locker locker(script_interpreter,
- // ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
- // ScriptInterpreterPython::Locker::FreeAcquiredLock);
- }
+// {
+// ScriptInterpreterPython::Locker locker(script_interpreter,
+// ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+// ScriptInterpreterPython::Locker::FreeAcquiredLock);
+// }
break;
case eInputReaderAsynchronousOutputWritten:
break;
case eInputReaderInterrupt:
- reader.SetIsDone(true);
+ {
+ PyThreadState* state = _PyThreadState_Current;
+ if (!state)
+ state = script_interpreter->m_command_thread_state;
+ if (state)
+ {
+ long tid = state->thread_id;
+ _PyThreadState_Current = state;
+ int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
+ if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p",
+ tid,num_threads,state);
+ }
+ else if (log)
+ log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL");
+ }
break;
case eInputReaderEndOfFile:
@@ -460,14 +392,14 @@ ScriptInterpreterPython::PythonInputRead
break;
case eInputReaderGotToken:
- if (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor() != -1)
+ if (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor() != -1)
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %lu", bytes,
bytes_len);
if (bytes && bytes_len)
- ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), bytes, bytes_len);
- ::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "\n", 1);
+ ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), bytes, bytes_len);
+ ::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), "\n", 1);
}
else
{
@@ -477,33 +409,30 @@ ScriptInterpreterPython::PythonInputRead
bytes_len);
reader.SetIsDone (true);
}
-
break;
case eInputReaderDone:
- {
- StreamString run_string;
- char error_str[1024];
- const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
- if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
{
- run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str());
- PyRun_SimpleString (run_string.GetData());
- run_string.Clear();
+ StreamString run_string;
+ char error_str[1024];
+ const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str));
+ if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL)
+ {
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin; sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+ }
+ // Restore terminal settings if they were validly saved
+ if (log)
+ log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader.");
- run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
- PyRun_SimpleString (run_string.GetData());
- run_string.Clear();
- }
- }
-
- // Restore terminal settings if they were validly saved
- if (log)
- log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader.");
-
- script_interpreter->RestoreTerminalState ();
-
- script_interpreter->m_embedded_python_pty.CloseMasterFileDescriptor();
+ script_interpreter->RestoreTerminalState ();
+
+ script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor();
+ }
break;
}
@@ -512,8 +441,10 @@ ScriptInterpreterPython::PythonInputRead
ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
ScriptInterpreter (interpreter, eScriptLanguagePython),
+ m_embedded_thread_pty (),
m_embedded_python_pty (),
m_embedded_thread_input_reader_sp (),
+ m_embedded_python_input_reader_sp (),
m_dbg_stdout (interpreter.GetDebugger().GetOutputFile().GetStream()),
m_new_sysout (NULL),
m_old_sysout (NULL),
@@ -522,7 +453,8 @@ ScriptInterpreterPython::ScriptInterpret
m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
m_terminal_state (),
m_session_is_active (false),
- m_valid_session (true)
+ m_valid_session (true),
+ m_command_thread_state (NULL)
{
static int g_initialized = false;
@@ -532,14 +464,14 @@ ScriptInterpreterPython::ScriptInterpret
g_initialized = true;
ScriptInterpreterPython::InitializePrivate ();
}
-
- Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock,
- ScriptInterpreterPython::Locker::FreeAcquiredLock);
m_dictionary_name.append("_dict");
StreamString run_string;
run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
@@ -560,8 +492,7 @@ ScriptInterpreterPython::ScriptInterpret
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
// and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
run_string.Clear();
- //run_string.Printf ("run_one_line (%s, 'from lldb.formatters import *; from lldb.formatters.objc import *; from lldb.formatters.cpp import *')", m_dictionary_name.c_str());
- run_string.Printf ("run_one_line (%s, 'import lldb.runtime.objc, lldb.formatters, lldb.formatters.objc, lldb.formatters.cpp')", m_dictionary_name.c_str());
+ run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
int new_count = Debugger::TestDebuggerRefCount();
@@ -570,7 +501,7 @@ ScriptInterpreterPython::ScriptInterpret
Debugger::Terminate();
run_string.Clear();
- run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %llu')", m_dictionary_name.c_str(),
+ run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
interpreter.GetDebugger().GetID());
PyRun_SimpleString (run_string.GetData());
@@ -578,6 +509,11 @@ ScriptInterpreterPython::ScriptInterpret
{
m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
+
+ // get the output file handle from the debugger (if any)
+ File& out_file = interpreter.GetDebugger().GetOutputFile();
+ if (out_file.IsValid())
+ ResetOutputFileHandle(out_file.GetStream());
}
ScriptInterpreterPython::~ScriptInterpreterPython ()
@@ -587,10 +523,19 @@ ScriptInterpreterPython::~ScriptInterpre
if (m_embedded_thread_input_reader_sp.get() != NULL)
{
m_embedded_thread_input_reader_sp->SetIsDone (true);
- m_embedded_python_pty.CloseSlaveFileDescriptor();
+ m_embedded_thread_pty.CloseSlaveFileDescriptor();
const InputReaderSP reader_sp = m_embedded_thread_input_reader_sp;
+ debugger.PopInputReader (reader_sp);
m_embedded_thread_input_reader_sp.reset();
+ }
+
+ if (m_embedded_python_input_reader_sp.get() != NULL)
+ {
+ m_embedded_python_input_reader_sp->SetIsDone (true);
+ m_embedded_python_pty.CloseSlaveFileDescriptor();
+ const InputReaderSP reader_sp = m_embedded_python_input_reader_sp;
debugger.PopInputReader (reader_sp);
+ m_embedded_python_input_reader_sp.reset();
}
if (m_new_sysout)
@@ -640,6 +585,10 @@ ScriptInterpreterPython::RestoreTerminal
void
ScriptInterpreterPython::LeaveSession ()
{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ if (log)
+ log->PutCString("ScriptInterpreterPython::LeaveSession()");
+
// checking that we have a valid thread state - since we use our own threading and locking
// in some (rare) cases during cleanup Python may end up believing we have no thread state
// and PyImport_AddModule will crash if that is the case - since that seems to only happen
@@ -664,33 +613,44 @@ ScriptInterpreterPython::LeaveSession ()
m_session_is_active = false;
}
-void
-ScriptInterpreterPython::EnterSession ()
+bool
+ScriptInterpreterPython::EnterSession (bool init_lldb_globals)
{
// If we have already entered the session, without having officially 'left' it, then there is no need to
// 'enter' it again.
-
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (m_session_is_active)
- return;
+ {
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i) session is already active, returning without doing anything", init_lldb_globals);
+ return false;
+ }
+
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i)", init_lldb_globals);
+
m_session_is_active = true;
StreamString run_string;
- run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %llu", m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
- run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%llu)", GetCommandInterpreter().GetDebugger().GetID());
- run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
- run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
- run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
- run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
- // Make sure STDIN is closed since when we run this as an embedded
- // interpreter we don't want someone to call "line = sys.stdin.readline()"
- // and lock up. We don't have multiple windows and when the interpreter is
- // embedded we don't know we should be feeding input to the embedded
- // interpreter or to the python sys.stdin. We also don't want to let python
- // play with the real stdin from this process, so we need to close it...
- //run_string.PutCString ("; sys.stdin.close()");
- run_string.PutCString ("')");
+ if (init_lldb_globals)
+ {
+ run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
+ run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
+ run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
+ run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
+ run_string.PutCString ("')");
+ }
+ else
+ {
+ // If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
+ run_string.Printf ( "run_one_line (%s, \"lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("\")");
+ }
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
@@ -711,6 +671,8 @@ ScriptInterpreterPython::EnterSession ()
if (PyErr_Occurred())
PyErr_Clear ();
+
+ return true;
}
static PyObject*
@@ -772,7 +734,7 @@ GenerateUniqueName (const char* base_nam
}
bool
-ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, bool enable_io)
+ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
{
if (!m_valid_session)
return false;
@@ -783,7 +745,7 @@ ScriptInterpreterPython::ExecuteOneLine
// method to pass the command string directly down to Python.
Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
bool success = false;
@@ -827,7 +789,7 @@ ScriptInterpreterPython::ExecuteOneLine
{
PyObject *pvalue = NULL;
{ // scope for PythonInputReaderManager
- PythonInputReaderManager py_input(enable_io ? this : NULL);
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
pvalue = PyObject_CallObject (pfunc, pargs);
}
Py_DECREF (pargs);
@@ -836,7 +798,7 @@ ScriptInterpreterPython::ExecuteOneLine
Py_DECREF (pvalue);
success = true;
}
- else if (PyErr_Occurred ())
+ else if (options.GetMaskoutErrors() && PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
@@ -873,7 +835,7 @@ ScriptInterpreterPython::InputReaderCall
)
{
lldb::thread_t embedded_interpreter_thread;
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (baton == NULL)
return 0;
@@ -883,13 +845,12 @@ ScriptInterpreterPython::InputReaderCall
if (script_interpreter->m_script_lang != eScriptLanguagePython)
return 0;
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
switch (notification)
{
case eInputReaderActivate:
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
if (!batch_mode)
{
out_stream->Printf ("Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.\n");
@@ -905,7 +866,7 @@ ScriptInterpreterPython::InputReaderCall
{
ScriptInterpreterPython::Locker locker(script_interpreter,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
@@ -922,7 +883,7 @@ ScriptInterpreterPython::InputReaderCall
if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
{
if (log)
- log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", embedded_interpreter_thread);
+ log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
Error detach_error;
Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
}
@@ -949,20 +910,9 @@ ScriptInterpreterPython::InputReaderCall
case eInputReaderReactivate:
{
- // Don't try and acquire the interpreter lock here because code like
- // this:
- //
- // (lldb) script
- // >>> v = lldb.frame.EvaluateExpression("collection->get_at_index(12)")
- //
- // This will cause the process to run. The interpreter lock is taken
- // by the input reader for the "script" command. If we try and acquire
- // the lock here, when the process runs it might deactivate this input
- // reader (if STDIN is hooked up to the inferior process) and
- // reactivate it when the process stops which will deadlock.
- //ScriptInterpreterPython::Locker locker(script_interpreter,
- // ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
- // ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ ScriptInterpreterPython::Locker locker (script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
break;
@@ -1004,7 +954,12 @@ ScriptInterpreterPython::InputReaderCall
break;
case eInputReaderDone:
- script_interpreter->LeaveSession ();
+ {
+ Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ script_interpreter->LeaveSession ();
+ }
// Restore terminal settings if they were validly saved
if (log)
@@ -1048,7 +1003,7 @@ ScriptInterpreterPython::ExecuteInterpre
if (error.Success())
{
debugger.PushInputReader (reader_sp);
- m_embedded_thread_input_reader_sp = reader_sp;
+ m_embedded_python_input_reader_sp = reader_sp;
}
}
}
@@ -1057,11 +1012,11 @@ bool
ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
ScriptInterpreter::ScriptReturnType return_type,
void *ret_value,
- bool enable_io)
+ const ExecuteScriptOptions &options)
{
Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
PyObject *py_return = NULL;
@@ -1094,7 +1049,7 @@ ScriptInterpreterPython::ExecuteOneLineW
if (in_string != NULL)
{
{ // scope for PythonInputReaderManager
- PythonInputReaderManager py_input(enable_io ? this : NULL);
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
if (py_return == NULL)
{
@@ -1198,8 +1153,6 @@ ScriptInterpreterPython::ExecuteOneLineW
success = PyArg_Parse (py_return, format, (char *) ret_value);
break;
}
- default:
- {}
}
Py_DECREF (py_return);
if (success)
@@ -1212,22 +1165,25 @@ ScriptInterpreterPython::ExecuteOneLineW
py_error = PyErr_Occurred();
if (py_error != NULL)
{
- if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
- PyErr_Print ();
- PyErr_Clear();
ret_success = false;
+ if (options.GetMaskoutErrors())
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ }
}
return ret_success;
}
bool
-ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, bool enable_io)
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
{
Locker locker(this,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
bool success = false;
@@ -1265,7 +1221,7 @@ ScriptInterpreterPython::ExecuteMultiple
if (compiled_code)
{
{ // scope for PythonInputReaderManager
- PythonInputReaderManager py_input(enable_io ? this : NULL);
+ PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
py_return = PyEval_EvalCode (compiled_code, globals, locals);
}
if (py_return != NULL)
@@ -1282,10 +1238,13 @@ ScriptInterpreterPython::ExecuteMultiple
py_error = PyErr_Occurred ();
if (py_error != NULL)
{
- if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
- PyErr_Print ();
- PyErr_Clear();
success = false;
+ if (options.GetMaskoutErrors())
+ {
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ }
}
return success;
@@ -1293,6 +1252,12 @@ ScriptInterpreterPython::ExecuteMultiple
static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+static const char *g_bkpt_command_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+ "def function(frame,bp_loc,internal_dict):\n"
+ " \"\"\"frame: the SBFrame for the location at which you stopped\n"
+ " bp_loc: an SBBreakpointLocation for the breakpoint location information\n"
+ " internal_dict: an LLDB support object not to be used\"\"\"";
+
size_t
ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
(
@@ -1305,17 +1270,17 @@ ScriptInterpreterPython::GenerateBreakpo
{
static StringList commands_in_progress;
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
switch (notification)
{
case eInputReaderActivate:
{
+
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
commands_in_progress.Clear();
if (!batch_mode)
{
- out_stream->Printf ("%s\n", g_reader_instructions);
+ out_stream->Printf ("%s\n", g_bkpt_command_reader_instructions);
if (reader.GetPrompt())
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
@@ -1327,10 +1292,14 @@ ScriptInterpreterPython::GenerateBreakpo
break;
case eInputReaderReactivate:
- if (reader.GetPrompt() && !batch_mode)
{
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush ();
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ if (reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
}
break;
@@ -1339,6 +1308,8 @@ ScriptInterpreterPython::GenerateBreakpo
case eInputReaderGotToken:
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
std::string temp_string (bytes, bytes_len);
commands_in_progress.AppendString (temp_string.c_str());
if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
@@ -1362,8 +1333,11 @@ ScriptInterpreterPython::GenerateBreakpo
case eInputReaderDone:
{
+ bool batch_mode = notification == eInputReaderDone ?
+ reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
+ true;
BreakpointOptions *bp_options = (BreakpointOptions *)baton;
- std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
data_ap->user_source.AppendList (commands_in_progress);
if (data_ap.get())
{
@@ -1378,6 +1352,7 @@ ScriptInterpreterPython::GenerateBreakpo
}
else if (!batch_mode)
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: No command attached to breakpoint.\n");
out_stream->Flush();
}
@@ -1386,6 +1361,7 @@ ScriptInterpreterPython::GenerateBreakpo
{
if (!batch_mode)
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
out_stream->Flush();
}
@@ -1411,13 +1387,13 @@ ScriptInterpreterPython::GenerateWatchpo
{
static StringList commands_in_progress;
- StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
- bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
-
switch (notification)
{
case eInputReaderActivate:
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+
commands_in_progress.Clear();
if (!batch_mode)
{
@@ -1433,10 +1409,14 @@ ScriptInterpreterPython::GenerateWatchpo
break;
case eInputReaderReactivate:
- if (reader.GetPrompt() && !batch_mode)
{
- out_stream->Printf ("%s", reader.GetPrompt());
- out_stream->Flush ();
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
+ if (reader.GetPrompt() && !batch_mode)
+ {
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+ }
}
break;
@@ -1445,6 +1425,8 @@ ScriptInterpreterPython::GenerateWatchpo
case eInputReaderGotToken:
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
+ bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
std::string temp_string (bytes, bytes_len);
commands_in_progress.AppendString (temp_string.c_str());
if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
@@ -1468,8 +1450,11 @@ ScriptInterpreterPython::GenerateWatchpo
case eInputReaderDone:
{
+ bool batch_mode = notification == eInputReaderDone ?
+ reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
+ true;
WatchpointOptions *wp_options = (WatchpointOptions *)baton;
- std::auto_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
data_ap->user_source.AppendList (commands_in_progress);
if (data_ap.get())
{
@@ -1484,6 +1469,7 @@ ScriptInterpreterPython::GenerateWatchpo
}
else if (!batch_mode)
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: No command attached to breakpoint.\n");
out_stream->Flush();
}
@@ -1492,6 +1478,7 @@ ScriptInterpreterPython::GenerateWatchpo
{
if (!batch_mode)
{
+ StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
out_stream->Flush();
}
@@ -1520,7 +1507,7 @@ ScriptInterpreterPython::CollectDataForB
bp_options, // baton
eInputReaderGranularityLine, // token size, for feeding data to callback function
"DONE", // end token
- "> ", // prompt
+ " ", // prompt
true); // echo input
if (err.Success())
@@ -1576,7 +1563,7 @@ void
ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
const char *oneliner)
{
- std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in breakpoint command list)
@@ -1599,7 +1586,7 @@ void
ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options,
const char *oneliner)
{
- std::auto_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in watchpoint command list)
@@ -1623,7 +1610,7 @@ ScriptInterpreterPython::ExportFunctionD
// Convert StringList to one long, newline delimited, const char *.
std::string function_def_string(function_def.CopyList());
- return ExecuteMultipleLines (function_def_string.c_str(), false);
+ return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
}
bool
@@ -1647,10 +1634,11 @@ ScriptInterpreterPython::GenerateFunctio
// Wrap everything up inside the function, increasing the indentation.
+ auto_generated_function.AppendString(" if True:");
for (int i = 0; i < num_lines; ++i)
{
sstr.Clear ();
- sstr.Printf (" %s", input.GetStringAtIndex (i));
+ sstr.Printf (" %s", input.GetStringAtIndex (i));
auto_generated_function.AppendString (sstr.GetData());
}
auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
@@ -1740,7 +1728,8 @@ ScriptInterpreterPython::GenerateTypeSyn
auto_generated_class.AppendString (sstr.GetData());
// Wrap everything up inside the class, increasing the indentation.
-
+ // we don't need to play any fancy indentation tricks here because there is no
+ // surrounding code whose indentation we need to honor
for (int i = 0; i < num_lines; ++i)
{
sstr.Clear ();
@@ -1762,10 +1751,300 @@ ScriptInterpreterPython::GenerateTypeSyn
}
lldb::ScriptInterpreterObjectSP
-ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name,
+ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp)
+{
+ if (class_name == NULL || class_name[0] == '\0')
+ return lldb::ScriptInterpreterObjectSP();
+
+ if (!process_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+ ret_val = g_swig_create_os_plugin (class_name,
+ m_dictionary_name.c_str(),
+ process_sp);
+ }
+
+ return MakeScriptObject(ret_val);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_register_info";
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_thread_info";
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+// GetPythonValueFormatString provides a system independent type safe way to
+// convert a variable's type into a python value format. Python value formats
+// are defined in terms of builtin C types and could change from system to
+// as the underlying typedef for uint* types, size_t, off_t and other values
+// change.
+
+template <typename T>
+const char *GetPythonValueFormatString(T t)
+{
+ assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type.");
+ return NULL;
+}
+template <> const char *GetPythonValueFormatString (char *) { return "s"; }
+template <> const char *GetPythonValueFormatString (char) { return "b"; }
+template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; }
+template <> const char *GetPythonValueFormatString (short) { return "h"; }
+template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; }
+template <> const char *GetPythonValueFormatString (int) { return "i"; }
+template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString (long) { return "l"; }
+template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; }
+template <> const char *GetPythonValueFormatString (long long) { return "L"; }
+template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; }
+template <> const char *GetPythonValueFormatString (float t) { return "f"; }
+template <> const char *GetPythonValueFormatString (double t) { return "d"; }
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp,
+ lldb::tid_t tid)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "get_register_data";
+ static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp,
+ lldb::tid_t tid,
+ lldb::addr_t context)
+{
+ Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
+
+ static char callee_name[] = "create_thread";
+ std::string param_format;
+ param_format += GetPythonValueFormatString(tid);
+ param_format += GetPythonValueFormatString(context);
+
+ if (!os_plugin_object_sp)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject();
+
+ if (implementor == NULL || implementor == Py_None)
+ return lldb::ScriptInterpreterObjectSP();
+
+ PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name);
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ if (pmeth == NULL || pmeth == Py_None)
+ {
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyCallable_Check(pmeth) == 0)
+ {
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+ return lldb::ScriptInterpreterObjectSP();
+ }
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Clear();
+ }
+
+ Py_XDECREF(pmeth);
+
+ // right now we know this function exists and is callable..
+ PyObject* py_return = PyObject_CallMethod(implementor, callee_name, ¶m_format[0], tid, context);
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name,
lldb::ValueObjectSP valobj)
{
- if (class_name.empty())
+ if (class_name == NULL || class_name[0] == '\0')
return lldb::ScriptInterpreterObjectSP();
if (!valobj.get())
@@ -1788,10 +2067,9 @@ ScriptInterpreterPython::CreateSynthetic
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(target);
- ret_val = g_swig_synthetic_script (class_name,
- python_interpreter->m_dictionary_name.c_str(),
- valobj);
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
}
return MakeScriptObject(ret_val);
@@ -2017,7 +2295,7 @@ ScriptInterpreterPython::RunEmbeddedPyth
{
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (log)
log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread starting...", baton);
@@ -2025,14 +2303,18 @@ ScriptInterpreterPython::RunEmbeddedPyth
char error_str[1024];
const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
- Locker locker(script_interpreter,
- ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
- ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
-
if (pty_slave_name != NULL)
{
StreamString run_string;
-
+
+ // Ensure we have the GIL before running any Python code.
+ // Since we're only running a few one-liners and then dropping to the interpreter (which will release the GIL when needed),
+ // we can just release the GIL after finishing our work.
+ // If finer-grained locking is desirable, we can lock and unlock the GIL only when calling a python function.
+ Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
@@ -2052,40 +2334,29 @@ ScriptInterpreterPython::RunEmbeddedPyth
// The following call drops into the embedded interpreter loop and stays there until the
// user chooses to exit from the Python interpreter.
+ // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
+ // a system call that can hang, and lock it when the syscall has returned.
- // When in the embedded interpreter, the user can call arbitrary system and Python stuff, which may require
- // the ability to run multi-threaded stuff, so we need to surround the call to the embedded interpreter with
- // calls to Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
-
- // We ALSO need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
- // PyGILState_Release. This is because this embedded interpreter is being run on a DIFFERENT THREAD than
- // the thread on which the call to Py_Initialize (and PyEval_InitThreads) was called. Those initializations
- // called PyGILState_Ensure on *that* thread, but it also needs to be called on *this* thread. Otherwise,
- // if the user calls Python code that does threading stuff, the interpreter state will be off, and things could
- // hang (it's happened before).
+ // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
+ // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
+ // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
+ // and things could hang (it's happened before).
- Py_BEGIN_ALLOW_THREADS
- PyGILState_STATE gstate = PyGILState_Ensure();
-
run_string.Printf ("run_python_interpreter (%s)", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
-
- PyGILState_Release (gstate);
- Py_END_ALLOW_THREADS
-
+
run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
-
+
run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
-
}
- if (script_interpreter->m_embedded_thread_input_reader_sp)
- script_interpreter->m_embedded_thread_input_reader_sp->SetIsDone (true);
+ if (script_interpreter->m_embedded_python_input_reader_sp)
+ script_interpreter->m_embedded_python_input_reader_sp->SetIsDone (true);
script_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
@@ -2096,9 +2367,12 @@ ScriptInterpreterPython::RunEmbeddedPyth
// Clean up the input reader and make the debugger pop it off the stack.
Debugger &debugger = script_interpreter->GetCommandInterpreter().GetDebugger();
- const InputReaderSP reader_sp = script_interpreter->m_embedded_thread_input_reader_sp;
- script_interpreter->m_embedded_thread_input_reader_sp.reset();
- debugger.PopInputReader (reader_sp);
+ const InputReaderSP reader_sp = script_interpreter->m_embedded_python_input_reader_sp;
+ if (reader_sp)
+ {
+ debugger.PopInputReader (reader_sp);
+ script_interpreter->m_embedded_python_input_reader_sp.reset();
+ }
return NULL;
}
@@ -2116,7 +2390,7 @@ ScriptInterpreterPython::PythonInputRead
return NULL;
}
-uint32_t
+size_t
ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor_sp)
{
if (!implementor_sp)
@@ -2134,8 +2408,7 @@ ScriptInterpreterPython::CalculateNumChi
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_calc_children (implementor);
+ ret_val = g_swig_calc_children (implementor);
}
return ret_val;
@@ -2155,21 +2428,18 @@ ScriptInterpreterPython::GetChildAtIndex
if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
return lldb::ValueObjectSP();
- void* child_ptr = NULL;
- lldb::SBValue* value_sb = NULL;
lldb::ValueObjectSP ret_val;
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- child_ptr = g_swig_get_child_index (implementor,idx);
+ void* child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != NULL && child_ptr != Py_None)
{
- value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
- if (value_sb == NULL)
+ lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == NULL)
Py_XDECREF(child_ptr);
else
- ret_val = value_sb->get_sp();
+ ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
}
else
{
@@ -2198,8 +2468,7 @@ ScriptInterpreterPython::GetIndexOfChild
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_get_index_child (implementor, child_name);
+ ret_val = g_swig_get_index_child (implementor, child_name);
}
return ret_val;
@@ -2223,16 +2492,97 @@ ScriptInterpreterPython::UpdateSynthProv
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_update_provider (implementor);
+ ret_val = g_swig_update_provider (implementor);
}
return ret_val;
}
bool
+ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp)
+{
+ bool ret_val = false;
+
+ if (!implementor_sp)
+ return ret_val;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_mighthavechildren_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this);
+ ret_val = g_swig_mighthavechildren_provider (implementor);
+ }
+
+ return ret_val;
+}
+
+static std::string
+ReadPythonBacktrace (PyObject* py_backtrace)
+{
+ PyObject* traceback_module = NULL,
+ *stringIO_module = NULL,
+ *stringIO_builder = NULL,
+ *stringIO_buffer = NULL,
+ *printTB = NULL,
+ *printTB_args = NULL,
+ *printTB_result = NULL,
+ *stringIO_getvalue = NULL,
+ *printTB_string = NULL;
+
+ std::string retval("backtrace unavailable");
+
+ if (py_backtrace && py_backtrace != Py_None)
+ {
+ traceback_module = PyImport_ImportModule("traceback");
+ stringIO_module = PyImport_ImportModule("StringIO");
+
+ if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None)
+ {
+ stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO");
+ if (stringIO_builder && stringIO_builder != Py_None)
+ {
+ stringIO_buffer = PyObject_CallObject(stringIO_builder, NULL);
+ if (stringIO_buffer && stringIO_buffer != Py_None)
+ {
+ printTB = PyObject_GetAttrString(traceback_module, "print_tb");
+ if (printTB && printTB != Py_None)
+ {
+ printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer);
+ printTB_result = PyObject_CallObject(printTB, printTB_args);
+ stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue");
+ if (stringIO_getvalue && stringIO_getvalue != Py_None)
+ {
+ printTB_string = PyObject_CallObject (stringIO_getvalue,NULL);
+ if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string))
+ retval.assign(PyString_AsString(printTB_string));
+ }
+ }
+ }
+ }
+ }
+ }
+ Py_XDECREF(traceback_module);
+ Py_XDECREF(stringIO_module);
+ Py_XDECREF(stringIO_builder);
+ Py_XDECREF(stringIO_buffer);
+ Py_XDECREF(printTB);
+ Py_XDECREF(printTB_args);
+ Py_XDECREF(printTB_result);
+ Py_XDECREF(stringIO_getvalue);
+ Py_XDECREF(printTB_string);
+ return retval;
+}
+
+bool
ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
bool can_reload,
+ bool init_session,
lldb_private::Error& error)
{
if (!pathname || !pathname[0])
@@ -2250,40 +2600,62 @@ ScriptInterpreterPython::LoadScriptingMo
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
{
- Locker py_lock(this);
-
FileSpec target_file(pathname, true);
+ std::string basename(target_file.GetFilename().GetCString());
+
+ StreamString command_stream;
+
+ // Before executing Pyton code, lock the GIL.
+ Locker py_lock (this,
+ Locker::AcquireLock | (init_session ? Locker::InitSession : 0),
+ Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
- // TODO: would we want to reject any other value?
if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
target_file.GetFileType() == FileSpec::eFileTypeUnknown)
{
- error.SetErrorString("invalid pathname");
- return false;
+ // if not a valid file of any sort, check if it might be a filename still
+ // dot can't be used but / and \ can, and if either is found, reject
+ if (strchr(pathname,'\\') || strchr(pathname,'/'))
+ {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+ basename = pathname; // not a filename, probably a package of some sort, let it go through
}
-
- const char* directory = target_file.GetDirectory().GetCString();
- std::string basename(target_file.GetFilename().GetCString());
-
- // now make sure that Python has "directory" in the search path
- StreamString command_stream;
- command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.append('%s');\n\n",
- directory,
- directory);
- bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), false);
- if (!syspath_retval)
+ else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
+ target_file.GetFileType() == FileSpec::eFileTypeRegular ||
+ target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink)
+ {
+ const char* directory = target_file.GetDirectory().GetCString();
+
+ // now make sure that Python has "directory" in the search path
+ StreamString command_stream;
+ command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n",
+ directory,
+ directory);
+ bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
+ if (!syspath_retval)
+ {
+ error.SetErrorString("Python sys.path handling failed");
+ return false;
+ }
+
+ // strip .py or .pyc extension
+ ConstString extension = target_file.GetFileNameExtension();
+ if (extension)
+ {
+ if (::strcmp(extension.GetCString(), "py") == 0)
+ basename.resize(basename.length()-3);
+ else if(::strcmp(extension.GetCString(), "pyc") == 0)
+ basename.resize(basename.length()-4);
+ }
+ }
+ else
{
- error.SetErrorString("Python sys.path handling failed");
+ error.SetErrorString("no known way to import this module specification");
return false;
}
- // strip .py or .pyc extension
- ConstString extension = target_file.GetFileNameExtension();
- if (::strcmp(extension.GetCString(), "py") == 0)
- basename.resize(basename.length()-3);
- else if(::strcmp(extension.GetCString(), "pyc") == 0)
- basename.resize(basename.length()-4);
-
// check if the module is already import-ed
command_stream.Clear();
command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
@@ -2291,7 +2663,9 @@ ScriptInterpreterPython::LoadScriptingMo
// this call will fail if the module does not exist (because the parameter to it is not a string
// but an actual Python module object, which is non-existant if the module was not imported before)
bool was_imported = (ExecuteOneLineWithReturn(command_stream.GetData(),
- ScriptInterpreterPython::eScriptReturnTypeInt, &refcount, false) && refcount > 0);
+ ScriptInterpreterPython::eScriptReturnTypeInt,
+ &refcount,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && refcount > 0);
if (was_imported == true && can_reload == false)
{
error.SetErrorString("module already imported");
@@ -2300,18 +2674,57 @@ ScriptInterpreterPython::LoadScriptingMo
// now actually do the import
command_stream.Clear();
- command_stream.Printf("import %s",basename.c_str());
- bool import_retval = ExecuteOneLine(command_stream.GetData(), NULL, false);
- if (!import_retval)
+ if (was_imported)
+ command_stream.Printf("reload(%s)",basename.c_str());
+ else
+ command_stream.Printf("import %s",basename.c_str());
+ bool import_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false).SetMaskoutErrors(false));
+ PyObject* py_error = PyErr_Occurred(); // per Python docs: "you do not need to Py_DECREF()" the return of this function
+
+ if (py_error || !import_retval) // check for failure of the import
{
- error.SetErrorString("Python import statement failed");
+ if (py_error) // if we have a Python error..
+ {
+ PyObject *type = NULL,*value = NULL,*traceback = NULL;
+ PyErr_Fetch (&type,&value,&traceback);
+
+ if (PyErr_GivenExceptionMatches (py_error, PyExc_ImportError)) // and it is an ImportError
+ {
+ if (value && value != Py_None)
+ error.SetErrorString(PyString_AsString(PyObject_Str(value)));
+ else
+ error.SetErrorString("ImportError raised by imported module");
+ }
+ else // any other error
+ {
+ // get the backtrace
+ std::string bt = ReadPythonBacktrace(traceback);
+
+ if (value && value != Py_None)
+ error.SetErrorStringWithFormat("Python error raised while importing module: %s - traceback: %s", PyString_AsString(PyObject_Str(value)),bt.c_str());
+ else
+ error.SetErrorStringWithFormat("Python raised an error while importing module - traceback: %s",bt.c_str());
+ }
+
+ Py_XDECREF(type);
+ Py_XDECREF(value);
+ Py_XDECREF(traceback);
+ }
+ else // we failed but have no error to explain why
+ {
+ error.SetErrorString("unknown error while importing module");
+ }
+
+ // anyway, clear the error indicator and return false
+ PyErr_Clear();
return false;
}
+ // if we are here, everything worked
// call __lldb_init_module(debugger,dict)
- if (!g_swig_call_module_init (basename,
- m_dictionary_name.c_str(),
- debugger_sp))
+ if (!g_swig_call_module_init (basename.c_str(),
+ m_dictionary_name.c_str(),
+ debugger_sp))
{
error.SetErrorString("calling __lldb_init_module failed");
return false;
@@ -2376,9 +2789,19 @@ ScriptInterpreterPython::RunScriptBasedC
std::string err_msg;
{
- Locker py_lock(this);
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession,
+ Locker::FreeLock | Locker::TearDownSession);
+
SynchronicityHandler synch_handler(debugger_sp,
synchronicity);
+
+ // we need to save the thread state when we first start the command
+ // because we might decide to interrupt it while some action is taking
+ // place outside of Python (e.g. printing to screen, waiting for the network, ...)
+ // in that case, _PyThreadState_Current will be NULL - and we would be unable
+ // to set the asynchronous exception - not a desirable situation
+ m_command_thread_state = _PyThreadState_Current;
PythonInputReaderManager py_input(this);
@@ -2401,22 +2824,42 @@ ScriptInterpreterPython::RunScriptBasedC
// in Python, a special attribute __doc__ contains the docstring
// for an object (function, method, class, ...) if any is defined
// Otherwise, the attribute's value is None
-std::string
-ScriptInterpreterPython::GetDocumentationForItem(const char* item)
+bool
+ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest)
{
+ dest.clear();
+ if (!item || !*item)
+ return false;
std::string command(item);
command += ".__doc__";
char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
if (ExecuteOneLineWithReturn (command.c_str(),
- ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
- &result_ptr, false) && result_ptr)
+ ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
+ &result_ptr,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)))
{
- return std::string(result_ptr);
+ if (result_ptr)
+ dest.assign(result_ptr);
+ return true;
}
else
- return std::string("");
+ {
+ StreamString str_stream;
+ str_stream.Printf("Function %s was not found. Containing module might be missing.",item);
+ dest.assign(str_stream.GetData());
+ return false;
+ }
+}
+
+std::unique_ptr<ScriptInterpreterLocker>
+ScriptInterpreterPython::AcquireInterpreterLock ()
+{
+ std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
+ Locker::AcquireLock | Locker::InitSession,
+ Locker::FreeLock | Locker::TearDownSession));
+ return py_lock;
}
void
@@ -2431,9 +2874,12 @@ ScriptInterpreterPython::InitializeInter
g_swig_get_child_index = LLDBSwigPython_GetChildAtIndex;
g_swig_get_index_child = LLDBSwigPython_GetIndexOfChildWithName;
g_swig_cast_to_sbvalue = LLDBSWIGPython_CastPyObjectToSBValue;
+ g_swig_get_valobj_sp_from_sbvalue = LLDBSWIGPython_GetValueObjectSPFromSBValue;
g_swig_update_provider = LLDBSwigPython_UpdateSynthProviderInstance;
+ g_swig_mighthavechildren_provider = LLDBSwigPython_MightHaveChildrenSynthProviderInstance;
g_swig_call_command = LLDBSwigPythonCallCommand;
g_swig_call_module_init = LLDBSwigPythonCallModuleInit;
+ g_swig_create_os_plugin = LLDBSWIGPythonCreateOSPlugin;
}
void
@@ -2446,7 +2892,18 @@ ScriptInterpreterPython::InitializePriva
TerminalState stdin_tty_state;
stdin_tty_state.Save(STDIN_FILENO, false);
- PyEval_InitThreads ();
+ PyGILState_STATE gstate;
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ bool threads_already_initialized = false;
+ if (PyEval_ThreadsInitialized ()) {
+ gstate = PyGILState_Ensure ();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
+ threads_already_initialized = true;
+ } else {
+ // InitThreads acquires the GIL if it hasn't been called before.
+ PyEval_InitThreads ();
+ }
Py_InitializeEx (0);
// Initialize SWIG after setting up python
@@ -2489,6 +2946,15 @@ ScriptInterpreterPython::InitializePriva
PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line; from termios import *");
+ if (threads_already_initialized) {
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release (gstate);
+ } else {
+ // We initialized the threads in this function, just unlock the GIL.
+ PyEval_SaveThread();
+ }
+
stdin_tty_state.Restore();
}
Modified: lldb/branches/lldb-platform-work/source/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Makefile?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Makefile (original)
+++ lldb/branches/lldb-platform-work/source/Makefile Thu Jun 6 19:06:43 2013
@@ -8,14 +8,30 @@
##===----------------------------------------------------------------------===##
LLDB_LEVEL := ..
-DIRS := API Breakpoint Commands Core Expression Host Interpreter Plugins Symbol Target Utility
+DIRS := API Breakpoint Commands Core DataFormatters Expression Host Interpreter Plugins Symbol Target Utility
LIBRARYNAME := lldbInitAndLog
BUILD_ARCHIVE = 1
+# Although LLVM makefiles provide $(HOST_OS), we cannot use that here because it is defined by including the $(LLDB_LEVEL)/Makefile
+# below. Instead, we use uname -s to detect the HOST_OS and generate LLDB_vers.c only on Mac. On Linux, the version number is
+# calculated in the same way as Clang's version.
+ifeq (Darwin,$(shell uname -s))
BUILT_SOURCES = LLDB_vers.c
+endif
+
SOURCES := lldb-log.cpp lldb.cpp
include $(LLDB_LEVEL)/Makefile
+ifeq ($(HOST_OS),Darwin)
LLDB_vers.c: $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/generate-vers.pl $(PROJ_SRC_DIR)/$(LLDB_LEVEL)/lldb.xcodeproj/project.pbxproj
"$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/scripts/generate-vers.pl" "$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/lldb.xcodeproj/project.pbxproj" > LLDB_vers.c
+else
+LLDB_REVISION := $(strip \
+ $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(LLVM_SRC_ROOT)/tools/lldb))
+
+LLDB_REPOSITORY := $(strip \
+ $(shell $(LLVM_SRC_ROOT)/utils/GetRepositoryPath $(LLVM_SRC_ROOT)/tools/lldb))
+
+CPP.Defines += -DLLDB_REVISION='"$(LLDB_REVISION)"' -DLLDB_REPOSITORY='"$(LLDB_REPOSITORY)"'
+endif
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp Thu Jun 6 19:06:43 2013
@@ -35,12 +35,7 @@
using namespace lldb;
using namespace lldb_private;
-static const char *pluginName = "ABIMacOSX_arm";
-static const char *pluginDesc = "Mac OS X ABI for arm targets";
-static const char *pluginShort = "abi.macosx-arm";
-
-
-static RegisterInfo g_register_infos[] =
+static RegisterInfo g_register_infos[] =
{
// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
// ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
@@ -332,10 +327,7 @@ ABIMacOSX_arm::GetArgumentValues (Thread
if (!reg_ctx)
return false;
- addr_t sp = reg_ctx->GetSP(0);
-
- if (!sp)
- return false;
+ addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx)
{
@@ -405,6 +397,14 @@ ABIMacOSX_arm::GetArgumentValues (Thread
}
else
{
+ if (sp == 0)
+ {
+ // Read the stack pointer if it already hasn't been read
+ sp = reg_ctx->GetSP(0);
+ if (sp == 0)
+ return false;
+ }
+
// Arguments 5 on up are on the stack
const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
Error error;
@@ -421,7 +421,7 @@ ABIMacOSX_arm::GetArgumentValues (Thread
ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
- lldb_private::ClangASTType &ast_type) const
+ lldb_private::ClangASTType &ast_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
@@ -507,6 +507,86 @@ ABIMacOSX_arm::GetReturnValueObjectImpl
return return_valobj_sp;
}
+Error
+ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast_context = new_value_sp->GetClangAST();
+ if (!ast_context)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ {
+ const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
+}
+
bool
ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
@@ -548,6 +628,8 @@ ABIMacOSX_arm::CreateFunctionEntryUnwind
// All other registers are the same.
unwind_plan.SetSourceName ("arm at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
return true;
}
@@ -571,9 +653,30 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("arm-apple-ios default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+
return true;
}
+// ARMv7 on iOS general purpose reg rules:
+// r0-r3 not preserved (used for argument passing)
+// r4-r6 preserved
+// r7 preserved (frame pointer)
+// r8 preserved
+// r9 not preserved (usable as volatile scratch register with iOS 3.x and later)
+// r10-r11 preserved
+// r12 not presrved
+// r13 preserved (stack pointer)
+// r14 not preserved (link register)
+// r15 preserved (pc)
+// cpsr not preserved (different rules for different bits)
+
+// ARMv7 on iOS floating point rules:
+// d0-d7 not preserved (aka s0-s15, q0-q3)
+// d8-d15 preserved (aka s16-s31, q4-q7)
+// d16-d31 not preserved (aka q8-q15)
+
bool
ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
{
@@ -611,28 +714,28 @@ ABIMacOSX_arm::RegisterIsVolatile (const
switch (name[1])
{
case '0':
- return name[2] == '\0'; // d0
+ return name[2] == '\0'; // d0 is volatile
case '1':
switch (name[2])
{
case '\0':
- return true; // d1;
+ return true; // d1 is volatile
case '6':
case '7':
case '8':
case '9':
- return name[3] == '\0'; // d16 - d19
+ return name[3] == '\0'; // d16 - d19 are volatile
default:
break;
}
break;
-
+
case '2':
switch (name[2])
{
case '\0':
- return true; // d2;
+ return true; // d2 is volatile
case '0':
case '1':
case '2':
@@ -643,7 +746,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const
case '7':
case '8':
case '9':
- return name[3] == '\0'; // d20 - d29
+ return name[3] == '\0'; // d20 - d29 are volatile
default:
break;
}
@@ -653,10 +756,10 @@ ABIMacOSX_arm::RegisterIsVolatile (const
switch (name[2])
{
case '\0':
- return true; // d3;
+ return true; // d3 is volatile
case '0':
case '1':
- return name[3] == '\0'; // d30 - d31
+ return name[3] == '\0'; // d30 - d31 are volatile
default:
break;
}
@@ -664,7 +767,61 @@ ABIMacOSX_arm::RegisterIsVolatile (const
case '5':
case '6':
case '7':
- return name[2] == '\0'; // d4 - d7
+ return name[2] == '\0'; // d4 - d7 are volatile
+
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 's')
+ {
+ switch (name[1])
+ {
+ case '0':
+ return name[2] == '\0'; // s0 is volatile
+
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s1 is volatile
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ return name[3] == '\0'; // s10 - s15 are volatile
+ default:
+ break;
+ }
+ break;
+
+ case '2':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s2 is volatile
+ default:
+ break;
+ }
+ break;
+
+ case '3':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // s3 is volatile
+ default:
+ break;
+ }
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[2] == '\0'; // s4 - s9 are volatile
default:
break;
@@ -679,8 +836,8 @@ ABIMacOSX_arm::RegisterIsVolatile (const
void
ABIMacOSX_arm::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Mac OS X ABI for arm targets",
CreateInstance);
}
@@ -690,19 +847,20 @@ ABIMacOSX_arm::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+ABIMacOSX_arm::GetPluginNameStatic()
+{
+ static ConstString g_name("macosx-arm");
+ return g_name;
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ABIMacOSX_arm::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-ABIMacOSX_arm::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h Thu Jun 6 19:06:43 2013
@@ -41,6 +41,9 @@ public:
GetArgumentValues (lldb_private::Thread &thread,
lldb_private::ValueList &values) const;
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
protected:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
@@ -90,6 +93,12 @@ public:
return pc & ~(lldb::addr_t)1;
}
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return false;
+ }
+
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
@@ -105,15 +114,15 @@ public:
static lldb::ABISP
CreateInstance (const lldb_private::ArchSpec &arch);
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp Thu Jun 6 19:06:43 2013
@@ -30,10 +30,6 @@
using namespace lldb;
using namespace lldb_private;
-static const char *pluginName = "ABIMacOSX_i386";
-static const char *pluginDesc = "Mac OS X ABI for i386 targets";
-static const char *pluginShort = "abi.macosx-i386";
-
enum
{
gcc_eax = 0,
@@ -453,7 +449,6 @@ ABIMacOSX_i386::PrepareNormalCall (Threa
switch (scalar.GetType())
{
case Scalar::e_void:
- default:
return false;
case Scalar::e_sint:
case Scalar::e_uint:
@@ -687,6 +682,86 @@ ABIMacOSX_i386::GetArgumentValues (Threa
return true;
}
+Error
+ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast_context = new_value_sp->GetClangAST();
+ if (!ast_context)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+ {
+ const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
+}
+
ValueObjectSP
ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
ClangASTType &ast_type) const
@@ -814,6 +889,7 @@ ABIMacOSX_i386::CreateFunctionEntryUnwin
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("i386 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
return true;
}
@@ -839,21 +915,25 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("i386 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
return true;
}
bool
ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
{
- return RegisterIsCalleeSaved (reg_info);
+ return !RegisterIsCalleeSaved (reg_info);
}
+// v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
+
bool
ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
{
if (reg_info)
{
- // Volatile registers include: ebx, ebp, esi, edi, esp, eip
+ // Saved registers are ebx, ebp, esi, edi, esp, eip
const char *name = reg_info->name;
if (name[0] == 'e')
{
@@ -861,22 +941,28 @@ ABIMacOSX_i386::RegisterIsCalleeSaved (c
{
case 'b':
if (name[2] == 'x' || name[2] == 'p')
- return name[0] == '\0';
+ return name[3] == '\0';
break;
case 'd':
if (name[2] == 'i')
- return name[0] == '\0';
+ return name[3] == '\0';
break;
case 'i':
if (name[2] == 'p')
- return name[0] == '\0';
+ return name[3] == '\0';
break;
case 's':
if (name[2] == 'i' || name[2] == 'p')
- return name[0] == '\0';
+ return name[3] == '\0';
break;
}
}
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
}
return false;
}
@@ -884,8 +970,8 @@ ABIMacOSX_i386::RegisterIsCalleeSaved (c
void
ABIMacOSX_i386::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Mac OS X ABI for i386 targets",
CreateInstance);
}
@@ -895,19 +981,21 @@ ABIMacOSX_i386::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+ABIMacOSX_i386::GetPluginNameStatic ()
+{
+ static ConstString g_short_name("abi.macosx-i386");
+ return g_short_name;
+
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ABIMacOSX_i386::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-ABIMacOSX_i386::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h Thu Jun 6 19:06:43 2013
@@ -51,6 +51,9 @@ public:
GetArgumentValues (lldb_private::Thread &thread,
lldb_private::ValueList &values) const;
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
protected:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
@@ -90,7 +93,13 @@ public:
// Just make sure the address is a valid 32 bit address.
return pc <= UINT32_MAX;
}
-
+
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return true;
+ }
+
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
@@ -109,12 +118,12 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp Thu Jun 6 19:06:43 2013
@@ -33,11 +33,6 @@
using namespace lldb;
using namespace lldb_private;
-static const char *pluginName = "ABISysV_x86_64";
-static const char *pluginDesc = "System V ABI for x86_64 targets";
-static const char *pluginShort = "abi.sysv-x86_64";
-
-
enum gcc_dwarf_regnums
{
gcc_dwarf_rax = 0,
@@ -81,22 +76,22 @@ enum gcc_dwarf_regnums
gcc_dwarf_stmm5,
gcc_dwarf_stmm6,
gcc_dwarf_stmm7,
- gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
- gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
- gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
- gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
- gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
- gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
- gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
- gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
- gcc_dwarf_ymm8 = gcc_dwarf_xmm8,
- gcc_dwarf_ymm9 = gcc_dwarf_xmm9,
- gcc_dwarf_ymm10 = gcc_dwarf_xmm10,
- gcc_dwarf_ymm11 = gcc_dwarf_xmm11,
- gcc_dwarf_ymm12 = gcc_dwarf_xmm12,
- gcc_dwarf_ymm13 = gcc_dwarf_xmm13,
- gcc_dwarf_ymm14 = gcc_dwarf_xmm14,
- gcc_dwarf_ymm15 = gcc_dwarf_xmm15
+ gcc_dwarf_ymm0,
+ gcc_dwarf_ymm1,
+ gcc_dwarf_ymm2,
+ gcc_dwarf_ymm3,
+ gcc_dwarf_ymm4,
+ gcc_dwarf_ymm5,
+ gcc_dwarf_ymm6,
+ gcc_dwarf_ymm7,
+ gcc_dwarf_ymm8,
+ gcc_dwarf_ymm9,
+ gcc_dwarf_ymm10,
+ gcc_dwarf_ymm11,
+ gcc_dwarf_ymm12,
+ gcc_dwarf_ymm13,
+ gcc_dwarf_ymm14,
+ gcc_dwarf_ymm15
};
enum gdb_regnums
@@ -158,22 +153,22 @@ enum gdb_regnums
gdb_xmm14 = 54,
gdb_xmm15 = 55,
gdb_mxcsr = 56,
- gdb_ymm0 = gdb_xmm0,
- gdb_ymm1 = gdb_xmm1,
- gdb_ymm2 = gdb_xmm2,
- gdb_ymm3 = gdb_xmm3,
- gdb_ymm4 = gdb_xmm4,
- gdb_ymm5 = gdb_xmm5,
- gdb_ymm6 = gdb_xmm6,
- gdb_ymm7 = gdb_xmm7,
- gdb_ymm8 = gdb_xmm8,
- gdb_ymm9 = gdb_xmm9,
- gdb_ymm10 = gdb_xmm10,
- gdb_ymm11 = gdb_xmm11,
- gdb_ymm12 = gdb_xmm12,
- gdb_ymm13 = gdb_xmm13,
- gdb_ymm14 = gdb_xmm14,
- gdb_ymm15 = gdb_xmm15
+ gdb_ymm0 = 57,
+ gdb_ymm1 = 58,
+ gdb_ymm2 = 59,
+ gdb_ymm3 = 60,
+ gdb_ymm4 = 61,
+ gdb_ymm5 = 62,
+ gdb_ymm6 = 63,
+ gdb_ymm7 = 64,
+ gdb_ymm8 = 65,
+ gdb_ymm9 = 66,
+ gdb_ymm10 = 67,
+ gdb_ymm11 = 68,
+ gdb_ymm12 = 69,
+ gdb_ymm13 = 70,
+ gdb_ymm14 = 71,
+ gdb_ymm15 = 72
};
@@ -315,10 +310,10 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
addr_t *arg5_ptr,
addr_t *arg6_ptr) const
{
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
- log->Printf("ABISysV_x86_64::PrepareTrivialCall\n(\n thread = %p\n sp = 0x%llx\n func_addr = 0x%llx\n return_addr = 0x%llx\n arg1_ptr = %p (0x%llx)\n arg2_ptr = %p (0x%llx)\n arg3_ptr = %p (0x%llx)\n)",
+ log->Printf("ABISysV_x86_64::PrepareTrivialCall\n(\n thread = %p\n sp = 0x%" PRIx64 "\n func_addr = 0x%" PRIx64 "\n return_addr = 0x%" PRIx64 "\n arg1_ptr = %p (0x%" PRIx64 ")\n arg2_ptr = %p (0x%" PRIx64 ")\n arg3_ptr = %p (0x%" PRIx64 ")\n)",
(void*)&thread,
(uint64_t)sp,
(uint64_t)func_addr,
@@ -336,7 +331,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("rdi", 0);
if (log)
- log->Printf("About to write arg1 (0x%llx) into %s", (uint64_t)*arg1_ptr, reg_info->name);
+ log->Printf("About to write arg1 (0x%" PRIx64 ") into %s", (uint64_t)*arg1_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg1_ptr))
return false;
@@ -345,7 +340,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("rsi", 0);
if (log)
- log->Printf("About to write arg2 (0x%llx) into %s", (uint64_t)*arg2_ptr, reg_info->name);
+ log->Printf("About to write arg2 (0x%" PRIx64 ") into %s", (uint64_t)*arg2_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg2_ptr))
return false;
@@ -353,7 +348,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("rdx", 0);
if (log)
- log->Printf("About to write arg3 (0x%llx) into %s", (uint64_t)*arg3_ptr, reg_info->name);
+ log->Printf("About to write arg3 (0x%" PRIx64 ") into %s", (uint64_t)*arg3_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg3_ptr))
return false;
@@ -361,7 +356,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("rcx", 0);
if (log)
- log->Printf("About to write arg4 (0x%llx) into %s", (uint64_t)*arg4_ptr, reg_info->name);
+ log->Printf("About to write arg4 (0x%" PRIx64 ") into %s", (uint64_t)*arg4_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg4_ptr))
return false;
@@ -369,7 +364,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("r8", 0);
if (log)
- log->Printf("About to write arg5 (0x%llx) into %s", (uint64_t)*arg5_ptr, reg_info->name);
+ log->Printf("About to write arg5 (0x%" PRIx64 ") into %s", (uint64_t)*arg5_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg5_ptr))
return false;
@@ -377,7 +372,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
{
reg_info = reg_ctx->GetRegisterInfoByName("r9", 0);
if (log)
- log->Printf("About to write arg6 (0x%llx) into %s", (uint64_t)*arg6_ptr, reg_info->name);
+ log->Printf("About to write arg6 (0x%" PRIx64 ") into %s", (uint64_t)*arg6_ptr, reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg6_ptr))
return false;
}
@@ -391,7 +386,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
// First, align the SP
if (log)
- log->Printf("16-byte aligning SP: 0x%llx to 0x%llx", (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
sp &= ~(0xfull); // 16-byte alignment
@@ -402,7 +397,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
reg_value.SetUInt64 (return_addr);
if (log)
- log->Printf("Pushing the return address onto the stack: new SP 0x%llx, return address 0x%llx", (uint64_t)sp, (uint64_t)return_addr);
+ log->Printf("Pushing the return address onto the stack: new SP 0x%" PRIx64 ", return address 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfoByName("rip");
Error error (reg_ctx->WriteRegisterValueToMemory(pc_reg_info, sp, pc_reg_info->byte_size, reg_value));
@@ -412,7 +407,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
// %rsp is set to the actual stack value.
if (log)
- log->Printf("Writing SP (0x%llx) down", (uint64_t)sp);
+ log->Printf("Writing SP (0x%" PRIx64 ") down", (uint64_t)sp);
if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoByName("rsp"), sp))
return false;
@@ -420,7 +415,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thre
// %rip is set to the address of the called function.
if (log)
- log->Printf("Writing new IP (0x%llx) down", (uint64_t)func_addr);
+ log->Printf("Writing new IP (0x%" PRIx64 ") down", (uint64_t)func_addr);
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
@@ -470,7 +465,7 @@ ABISysV_x86_64::GetArgumentValues (Threa
// For now, assume that the types in the AST values come from the Target's
// scratch AST.
- clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+ clang::ASTContext *ast = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
// Extract the register context so we can read arguments from registers
@@ -522,7 +517,7 @@ ABISysV_x86_64::GetArgumentValues (Threa
if (ClangASTContext::IsIntegerType (value_type, is_signed))
{
- size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+ size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, value_type);
ReadIntegerArgument(value->GetScalar(),
bit_width,
@@ -550,142 +545,276 @@ ABISysV_x86_64::GetArgumentValues (Threa
return true;
}
+Error
+ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast = new_value_sp->GetClangAST();
+ if (!ast)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
+
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, value_type);
+ if (bit_width <= 64)
+ {
+ const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ RegisterValue xmm0_value;
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+
+ data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ xmm0_value.SetBytes(buffer, 16, byte_order);
+ reg_ctx->WriteRegister(xmm0_info, xmm0_value);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
ValueObjectSP
ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &ast_type) const
+ ClangASTType &ast_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- clang_type_t value_type = ast_type.GetOpaqueQualType();
- if (!value_type)
+ clang_type_t return_value_type = ast_type.GetOpaqueQualType();
+ if (!return_value_type)
return return_valobj_sp;
- clang::ASTContext *ast_context = ast_type.GetASTContext();
- if (!ast_context)
+ clang::ASTContext *ast = ast_type.GetASTContext();
+ if (!ast)
return return_valobj_sp;
- value.SetContext (Value::eContextTypeClangType, value_type);
+ value.SetContext (Value::eContextTypeClangType, return_value_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- bool is_signed;
- bool is_complex;
- uint32_t count;
-
- if (ClangASTContext::IsIntegerType (value_type, is_signed))
+ const uint32_t type_flags = ClangASTContext::GetTypeInfo (return_value_type, ast, NULL);
+ if (type_flags & ClangASTContext::eTypeIsScalar)
{
- // For now, assume that the types in the AST values come from the Target's
- // scratch AST.
-
-
- // Extract the register context so we can read arguments from registers
-
- size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
- unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
-
- switch (bit_width)
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & ClangASTContext::eTypeIsInteger)
{
- default:
- case 128:
- // Scalar can't hold 128-bit literals, so we don't handle this
- return return_valobj_sp;
- case 64:
- if (is_signed)
- value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
- else
- value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
- break;
- case 32:
- if (is_signed)
- value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
- else
- value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
- break;
- case 16:
- if (is_signed)
- value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
- else
- value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
- break;
- case 8:
- if (is_signed)
- value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
- else
- value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
- break;
+ // Extract the register context so we can read arguments from registers
+
+ const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type);
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
+ const bool is_signed = (type_flags & ClangASTContext::eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
}
- }
- else if (ClangASTContext::IsFloatingPointType(value_type, count, is_complex))
- {
- // Don't handle complex yet.
- if (is_complex)
- return return_valobj_sp;
-
- size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
- if (bit_width <= 64)
+ else if (type_flags & ClangASTContext::eTypeIsFloat)
{
- const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
- RegisterValue xmm0_value;
- if (reg_ctx->ReadRegister (xmm0_info, xmm0_value))
+ if (type_flags & ClangASTContext::eTypeIsComplex)
{
- DataExtractor data;
- if (xmm0_value.GetData(data))
+ // Don't handle complex yet.
+ }
+ else
+ {
+ const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type);
+ if (byte_size <= sizeof(long double))
{
- uint32_t offset = 0;
- switch (bit_width)
+ const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ RegisterValue xmm0_value;
+ if (reg_ctx->ReadRegister (xmm0_info, xmm0_value))
{
- default:
- return return_valobj_sp;
- case 32:
- value.GetScalar() = (float) data.GetFloat(&offset);
- break;
- case 64:
- value.GetScalar() = (double) data.GetDouble(&offset);
- break;
+ DataExtractor data;
+ if (xmm0_value.GetData(data))
+ {
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = (float) data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = (double) data.GetDouble(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ // Don't handle long double since that can be encoded as 80 bit floats...
+ }
+ }
}
}
}
}
- else if (bit_width == 128)
- {
- // FIXME: x86_64 returns long doubles in stmm0, which is in some 80 bit long double
- // format, and so we'll have to write some code to convert that into 128 bit long doubles.
-// const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("stmm0", 0);
-// RegisterValue st0_value;
-// if (reg_ctx->ReadRegister (st0_info, st0_value))
-// {
-// DataExtractor data;
-// if (st0_value.GetData(data))
-// {
-// uint32_t offset = 0;
-// value.GetScalar() = (long double) data.GetLongDouble (&offset);
-// return true;
-// }
-// }
-
- return return_valobj_sp;
- }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ ast_type.GetASTContext(),
+ value,
+ ConstString(""));
+
}
- else if (ClangASTContext::IsPointerType (value_type))
+ else if (type_flags & ClangASTContext::eTypeIsPointer)
{
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+ value.SetValueType(Value::eValueTypeScalar);
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ ast_type.GetASTContext(),
+ value,
+ ConstString(""));
}
- else
+ else if (type_flags & ClangASTContext::eTypeIsVector)
{
- return return_valobj_sp;
+ const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type);
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
+ if (altivec_reg == NULL)
+ {
+ altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ if (altivec_reg == NULL)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ }
+
+ if (altivec_reg)
+ {
+ if (byte_size <= altivec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ ast,
+ return_value_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
}
- // If we get here, we have a valid Value, so make our ValueObject out of it:
-
- return_valobj_sp = ValueObjectConstResult::Create(
- thread.GetStackFrameAtIndex(0).get(),
- ast_type.GetASTContext(),
- value,
- ConstString(""));
return return_valobj_sp;
}
@@ -699,20 +828,20 @@ ABISysV_x86_64::GetReturnValueObjectImpl
if (return_valobj_sp)
return return_valobj_sp;
- clang_type_t ret_value_type = ast_type.GetOpaqueQualType();
- if (!ret_value_type)
+ clang_type_t return_value_type = ast_type.GetOpaqueQualType();
+ if (!return_value_type)
return return_valobj_sp;
- clang::ASTContext *ast_context = ast_type.GetASTContext();
- if (!ast_context)
+ clang::ASTContext *ast = ast_type.GetASTContext();
+ if (!ast)
return return_valobj_sp;
RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
if (!reg_ctx_sp)
return return_valobj_sp;
- size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, ret_value_type);
- if (ClangASTContext::IsAggregateType(ret_value_type))
+ size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, return_value_type);
+ if (ClangASTContext::IsAggregateType(return_value_type))
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -745,7 +874,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far
- uint32_t num_children = ClangASTContext::GetNumFields (ast_context, ret_value_type);
+ uint32_t num_children = ClangASTContext::GetNumFields (ast, return_value_type);
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -758,8 +887,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl
bool is_complex;
uint32_t count;
- clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx, name, &field_bit_offset, NULL, NULL);
- size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, field_clang_type);
+ clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast, return_value_type, idx, name, &field_bit_offset, NULL, NULL);
+ size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast, field_clang_type);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -841,8 +970,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl
else
{
uint64_t next_field_bit_offset = 0;
- clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context,
- ret_value_type,
+ clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast,
+ return_value_type,
idx + 1,
name,
&next_field_bit_offset,
@@ -867,8 +996,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl
else
{
uint64_t prev_field_bit_offset = 0;
- clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context,
- ret_value_type,
+ clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast,
+ return_value_type,
idx - 1,
name,
&prev_field_bit_offset,
@@ -921,7 +1050,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl
// These two tests are just sanity checks. If I somehow get the
// type calculation wrong above it is better to just return nothing
- // than to assert or crash.
+ // than to assert or crash.
if (!copy_from_extractor)
return return_valobj_sp;
if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
@@ -938,13 +1067,19 @@ ABISysV_x86_64::GetReturnValueObjectImpl
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- ast_context,
- ret_value_type,
+ ast,
+ return_value_type,
ConstString(""),
return_ext);
}
}
+
+ // FIXME: This is just taking a guess, rax may very well no longer hold the return storage location.
+ // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+ // return, and if we are at the first instruction and if so stash away the return location. Then we would
+ // only return the memory return value if we know it is valid.
+
if (is_memory)
{
unsigned rax_id = reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
@@ -995,6 +1130,7 @@ ABISysV_x86_64::CreateFunctionEntryUnwin
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("x86_64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
return true;
}
@@ -1046,6 +1182,8 @@ ABISysV_x86_64::CreateDefaultUnwindPlan
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("x86_64 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
return true;
}
@@ -1057,14 +1195,23 @@ ABISysV_x86_64::RegisterIsVolatile (cons
-
+// See "Register Usage" in the
+// "System V Application Binary Interface"
+// "AMD64 Architecture Processor Supplement"
+// (or "x86-64(tm) Architecture Processor Supplement" in earlier revisions)
+// Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
+// current version is 0.99.6 released 2012-05-15 at http://x86-64.org/documentation/abi.pdf
bool
ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
{
if (reg_info)
{
- // Volatile registers include: rbx, rbp, rsp, r12, r13, r14, r15, rip
+ // Preserved registers are :
+ // rbx, rsp, rbp, r12, r13, r14, r15
+ // mxcsr (partially preserved)
+ // x87 control word
+
const char *name = reg_info->name;
if (name[0] == 'r')
{
@@ -1075,6 +1222,16 @@ ABISysV_x86_64::RegisterIsCalleeSaved (c
return name[3] == '\0';
break;
+ default:
+ break;
+ }
+ }
+
+ // Accept shorter-variant versions, rbx/ebx, rip/ eip, etc.
+ if (name[0] == 'r' || name[0] == 'e')
+ {
+ switch (name[1])
+ {
case 'b': // rbp, rbx
if (name[2] == 'p' || name[2] == 'x')
return name[3] == '\0';
@@ -1090,10 +1247,14 @@ ABISysV_x86_64::RegisterIsCalleeSaved (c
return name[3] == '\0';
break;
- default:
- break;
}
}
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
}
return false;
}
@@ -1103,8 +1264,8 @@ ABISysV_x86_64::RegisterIsCalleeSaved (c
void
ABISysV_x86_64::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for x86_64 targets",
CreateInstance);
}
@@ -1114,19 +1275,20 @@ ABISysV_x86_64::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+ABISysV_x86_64::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-x86_64");
+ return g_name;
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ABISysV_x86_64::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-ABISysV_x86_64::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
Modified: lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h Thu Jun 6 19:06:43 2013
@@ -45,10 +45,14 @@ public:
GetArgumentValues (lldb_private::Thread &thread,
lldb_private::ValueList &values) const;
+ virtual lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
protected:
lldb::ValueObjectSP
GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
+ lldb_private::ClangASTType &ast_type) const;
+
public:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
@@ -87,7 +91,13 @@ public:
// aren't fixed width...
return true;
}
-
+
+ virtual bool
+ FunctionCallsChangeCFA ()
+ {
+ return true;
+ }
+
virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
@@ -102,15 +112,15 @@ public:
static lldb::ABISP
CreateInstance (const lldb_private::ArchSpec &arch);
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
Removed: lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp (removed)
@@ -1,525 +0,0 @@
-//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DisassemblerLLVM.h"
-
-#include "llvm-c/EnhancedDisassembly.h"
-#include "llvm/Support/TargetSelect.h"
-
-#include "lldb/Core/Address.h"
-#include "lldb/Core/DataExtractor.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Stream.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Symbol/SymbolContext.h"
-
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/Target.h"
-
-#include <assert.h>
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-static int
-DataExtractorByteReader (uint8_t *byte, uint64_t address, void *arg)
-{
- DataExtractor &extractor = *((DataExtractor *)arg);
-
- if (extractor.ValidOffset(address))
- {
- *byte = *(extractor.GetDataStart() + address);
- return 0;
- }
- else
- {
- return -1;
- }
-}
-
-namespace {
- struct RegisterReaderArg {
- const lldb::addr_t instructionPointer;
- const EDDisassemblerRef disassembler;
-
- RegisterReaderArg(lldb::addr_t ip,
- EDDisassemblerRef dis) :
- instructionPointer(ip),
- disassembler(dis)
- {
- }
- };
-}
-
-static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
-{
- uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
- EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
-
- if (EDRegisterIsProgramCounter(disassembler, regID)) {
- *value = instructionPointer;
- return 0;
- }
-
- return -1;
-}
-
-InstructionLLVM::InstructionLLVM (const Address &addr,
- AddressClass addr_class,
- EDDisassemblerRef disassembler,
- llvm::Triple::ArchType arch_type) :
- Instruction (addr, addr_class),
- m_disassembler (disassembler),
- m_inst (NULL),
- m_arch_type (arch_type)
-{
-}
-
-InstructionLLVM::~InstructionLLVM()
-{
- if (m_inst)
- {
- EDReleaseInst(m_inst);
- m_inst = NULL;
- }
-}
-
-static void
-PadString(Stream *s, const std::string &str, size_t width)
-{
- int diff = width - str.length();
-
- if (diff > 0)
- s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
- else
- s->Printf("%s ", str.c_str());
-}
-static void
-AddSymbolicInfo (const ExecutionContext *exe_ctx,
- StreamString &comment,
- uint64_t operand_value,
- const Address &inst_addr)
-{
- Address so_addr;
- Target *target = NULL;
- if (exe_ctx)
- target = exe_ctx->GetTargetPtr();
- if (target && !target->GetSectionLoadList().IsEmpty())
- {
- if (target->GetSectionLoadList().ResolveLoadAddress(operand_value, so_addr))
- so_addr.Dump (&comment,
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL,
- Address::DumpStyleResolvedDescriptionNoModule,
- Address::DumpStyleSectionNameOffset);
- }
- else
- {
- ModuleSP module_sp (inst_addr.GetModule());
- if (module_sp)
- {
- if (module_sp->ResolveFileAddress(operand_value, so_addr))
- so_addr.Dump (&comment,
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL,
- Address::DumpStyleResolvedDescriptionNoModule,
- Address::DumpStyleSectionNameOffset);
- }
- }
-}
-
-#include "llvm/ADT/StringRef.h"
-static inline void StripSpaces(llvm::StringRef &Str)
-{
- while (!Str.empty() && isspace(Str[0]))
- Str = Str.substr(1);
- while (!Str.empty() && isspace(Str.back()))
- Str = Str.substr(0, Str.size()-1);
-}
-static inline void RStrip(llvm::StringRef &Str, char c)
-{
- if (!Str.empty() && Str.back() == c)
- Str = Str.substr(0, Str.size()-1);
-}
-// Aligns the raw disassembly (passed as 'str') with the rest of edis'ed disassembly output.
-// This is called from non-raw mode when edis of the current m_inst fails for some reason.
-static void
-Align(Stream *s, const char *str, size_t opcodeColWidth, size_t operandColWidth)
-{
- llvm::StringRef raw_disasm(str);
- StripSpaces(raw_disasm);
- // Split the raw disassembly into opcode and operands.
- std::pair<llvm::StringRef, llvm::StringRef> p = raw_disasm.split('\t');
- PadString(s, p.first, opcodeColWidth);
- if (!p.second.empty())
- PadString(s, p.second, operandColWidth);
-}
-
-#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
-
-void
-InstructionLLVM::CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx)
-{
- const int num_tokens = EDNumTokens(m_inst);
- if (num_tokens > 0)
- {
- const char *token_cstr = NULL;
- int currentOpIndex = -1;
- StreamString comment;
- uint32_t addr_nibble_size = 8;
- addr_t base_addr = LLDB_INVALID_ADDRESS;
- Target *target = exe_ctx ? exe_ctx->GetTargetPtr() : NULL;
- if (target && !target->GetSectionLoadList().IsEmpty())
- base_addr = GetAddress().GetLoadAddress (target);
- if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr = GetAddress().GetFileAddress ();
- addr_nibble_size = target->GetArchitecture().GetAddressByteSize() * 2;
-
- lldb::addr_t PC = base_addr + EDInstByteSize(m_inst);
-
- // When executing an ARM instruction, PC reads as the address of the
- // current instruction plus 8. And for Thumb, it is plus 4.
- if (m_arch_type == llvm::Triple::arm)
- PC = base_addr + 8;
- else if (m_arch_type == llvm::Triple::thumb)
- PC = base_addr + 4;
-
- RegisterReaderArg rra(PC, m_disassembler);
-
- for (int token_idx = 0; token_idx < num_tokens; ++token_idx)
- {
- EDTokenRef token;
- if (EDGetToken(&token, m_inst, token_idx))
- break;
-
- if (EDTokenIsOpcode(token) == 1)
- {
- if (EDGetTokenString(&token_cstr, token) == 0) // 0 on success
- {
- if (token_cstr)
- m_opcode_name.assign(token_cstr);
- }
- }
- else
- {
- int operandIndex = EDOperandIndexForToken(token);
-
- if (operandIndex >= 0)
- {
- if (operandIndex != currentOpIndex)
- {
- currentOpIndex = operandIndex;
- EDOperandRef operand;
-
- if (!EDGetOperand(&operand, m_inst, currentOpIndex))
- {
- if (EDOperandIsMemory(operand))
- {
- uint64_t operand_value;
-
- if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
- {
- comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value);
- AddSymbolicInfo (exe_ctx, comment, operand_value, GetAddress());
- }
- }
- }
- }
- }
- if (m_mnemocics.empty() && EDTokenIsWhitespace (token) == 1)
- continue;
- if (EDGetTokenString (&token_cstr, token))
- break;
- m_mnemocics.append (token_cstr);
- }
- }
- // FIXME!!!
- // Workaround for llvm::tB's operands not properly parsed by ARMAsmParser.
- if (m_arch_type == llvm::Triple::thumb && m_opcode_name.compare("b") == 0)
- {
- const char *inst_str;
- const char *pos = NULL;
- comment.Clear();
- if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL)
- {
- uint64_t operand_value = PC + atoi(++pos);
- // Put the address value into the operands.
- comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value);
- AddSymbolicInfo (exe_ctx, comment, operand_value, GetAddress());
- }
- }
- // Yet more workaround for "bl #..." and "blx #...".
- if ((m_arch_type == llvm::Triple::arm || m_arch_type == llvm::Triple::thumb) &&
- (m_opcode_name.compare("bl") == 0 || m_opcode_name.compare("blx") == 0))
- {
- const char *inst_str;
- const char *pos = NULL;
- comment.Clear();
- if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL)
- {
- if (m_arch_type == llvm::Triple::thumb && m_opcode_name.compare("blx") == 0)
- {
- // A8.6.23 BLX (immediate)
- // Target Address = Align(PC,4) + offset value
- PC = AlignPC(PC);
- }
- uint64_t operand_value = PC + atoi(++pos);
- // Put the address value into the comment.
- comment.Printf("0x%*.*llx ", addr_nibble_size, addr_nibble_size, operand_value);
- // And the original token string into the operands.
-// llvm::StringRef Str(pos - 1);
-// RStrip(Str, '\n');
-// operands.PutCString(Str.str().c_str());
- AddSymbolicInfo (exe_ctx, comment, operand_value, GetAddress());
- }
- }
- // END of workaround.
-
- m_comment.swap (comment.GetString());
- }
-}
-
-bool
-InstructionLLVM::DoesBranch() const
-{
- return EDInstIsBranch(m_inst);
-}
-
-size_t
-InstructionLLVM::Decode (const Disassembler &disassembler,
- const lldb_private::DataExtractor &data,
- uint32_t data_offset)
-{
- if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
- {
- const int byte_size = EDInstByteSize(m_inst);
- uint32_t offset = data_offset;
- // Make a copy of the opcode in m_opcode
- switch (disassembler.GetArchitecture().GetMachine())
- {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (byte_size)
- {
- case 2:
- m_opcode.SetOpcode16 (data.GetU16 (&offset));
- break;
-
- case 4:
- {
- if (GetAddressClass() == eAddressClassCodeAlternateISA)
- {
- // If it is a 32-bit THUMB instruction, we need to swap the upper & lower halves.
- uint32_t orig_bytes = data.GetU32 (&offset);
- uint16_t upper_bits = (orig_bytes >> 16) & ((1u << 16) - 1);
- uint16_t lower_bits = orig_bytes & ((1u << 16) - 1);
- uint32_t swapped = (lower_bits << 16) | upper_bits;
- m_opcode.SetOpcode32 (swapped);
- }
- else
- m_opcode.SetOpcode32 (data.GetU32 (&offset));
- }
- break;
-
- default:
- assert (!"Invalid ARM opcode size");
- break;
- }
- break;
-
- default:
- assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
- break;
- }
- return byte_size;
- }
- else
- return 0;
-}
-
-static inline EDAssemblySyntax_t
-SyntaxForArchSpec (const ArchSpec &arch)
-{
- switch (arch.GetMachine ())
- {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- return kEDAssemblySyntaxX86ATT;
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- return kEDAssemblySyntaxARMUAL;
- default:
- break;
- }
- return (EDAssemblySyntax_t)0; // default
-}
-
-Disassembler *
-DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
-{
- std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
-
- if (disasm_ap.get() && disasm_ap->IsValid())
- return disasm_ap.release();
-
- return NULL;
-}
-
-DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
- Disassembler (arch),
- m_disassembler (NULL),
- m_disassembler_thumb (NULL) // For ARM only
-{
- // Initialize the LLVM objects needed to use the disassembler.
- static struct InitializeLLVM {
- InitializeLLVM() {
- llvm::InitializeAllTargetInfos();
- llvm::InitializeAllTargetMCs();
- llvm::InitializeAllAsmParsers();
- llvm::InitializeAllDisassemblers();
- }
- } InitializeLLVM;
-
- const std::string &arch_triple = arch.GetTriple().str();
- if (!arch_triple.empty())
- {
- if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
- m_disassembler = NULL;
- llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
- // Don't have the lldb::Triple::thumb architecture here. If someone specifies
- // "thumb" as the architecture, we want a thumb only disassembler. But if any
- // architecture starting with "arm" if specified, we want to auto detect the
- // arm/thumb code automatically using the AddressClass from section offset
- // addresses.
- if (llvm_arch == llvm::Triple::arm)
- {
- ArchSpec thumb_arch(arch);
- thumb_arch.GetTriple().setArchName(llvm::StringRef("thumbv7"));
- std::string thumb_triple(thumb_arch.GetTriple().getTriple());
- if (EDGetDisassembler(&m_disassembler_thumb, thumb_triple.c_str(), kEDAssemblySyntaxARMUAL))
- m_disassembler_thumb = NULL;
- }
- }
-}
-
-DisassemblerLLVM::~DisassemblerLLVM()
-{
-}
-
-size_t
-DisassemblerLLVM::DecodeInstructions
-(
- const Address &base_addr,
- const DataExtractor& data,
- uint32_t data_offset,
- uint32_t num_instructions,
- bool append
-)
-{
- if (m_disassembler == NULL)
- return 0;
-
- size_t total_inst_byte_size = 0;
-
- if (!append)
- m_instruction_list.Clear();
-
- while (data.ValidOffset(data_offset) && num_instructions)
- {
- Address inst_addr (base_addr);
- inst_addr.Slide(data_offset);
-
- bool use_thumb = false;
- // If we have a thumb disassembler, then we have an ARM architecture
- // so we need to check what the instruction address class is to make
- // sure we shouldn't be disassembling as thumb...
- AddressClass inst_address_class = eAddressClassInvalid;
- if (m_disassembler_thumb)
- {
- inst_address_class = inst_addr.GetAddressClass ();
- if (inst_address_class == eAddressClassCodeAlternateISA)
- use_thumb = true;
- }
-
- InstructionSP inst_sp (new InstructionLLVM (inst_addr,
- inst_address_class,
- use_thumb ? m_disassembler_thumb : m_disassembler,
- use_thumb ? llvm::Triple::thumb : m_arch.GetMachine()));
-
- size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
-
- if (inst_byte_size == 0)
- break;
-
- m_instruction_list.Append (inst_sp);
-
- total_inst_byte_size += inst_byte_size;
- data_offset += inst_byte_size;
- num_instructions--;
- }
-
- return total_inst_byte_size;
-}
-
-void
-DisassemblerLLVM::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
-}
-
-void
-DisassemblerLLVM::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
-}
-
-
-const char *
-DisassemblerLLVM::GetPluginNameStatic()
-{
- return "llvm-edis";
-}
-
-const char *
-DisassemblerLLVM::GetPluginDescriptionStatic()
-{
- return "Disassembler that uses the LLVM enhanced disassembler to disassemble i386, x86_64 and ARM.";
-}
-
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-const char *
-DisassemblerLLVM::GetPluginName()
-{
- return "DisassemblerLLVM";
-}
-
-const char *
-DisassemblerLLVM::GetShortPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-DisassemblerLLVM::GetPluginVersion()
-{
- return 1;
-}
-
Removed: lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVM.h (removed)
@@ -1,105 +0,0 @@
-//===-- DisassemblerLLVM.h --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_DisassemblerLLVM_h_
-#define liblldb_DisassemblerLLVM_h_
-
-
-#include "llvm-c/EnhancedDisassembly.h"
-
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Host/Mutex.h"
-
-class InstructionLLVM : public lldb_private::Instruction
-{
-public:
- InstructionLLVM (const lldb_private::Address &addr,
- lldb::AddressClass addr_class,
- EDDisassemblerRef disassembler,
- llvm::Triple::ArchType arch_type);
-
- virtual
- ~InstructionLLVM();
-
- virtual bool
- DoesBranch () const;
-
- virtual size_t
- Decode (const lldb_private::Disassembler &disassembler,
- const lldb_private::DataExtractor &data,
- uint32_t data_offset);
-
- virtual void
- CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext* exe_ctx);
-
-protected:
- EDDisassemblerRef m_disassembler;
- EDInstRef m_inst;
- llvm::Triple::ArchType m_arch_type;
-};
-
-
-class DisassemblerLLVM : public lldb_private::Disassembler
-{
-public:
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static const char *
- GetPluginNameStatic();
-
- static const char *
- GetPluginDescriptionStatic();
-
- static lldb_private::Disassembler *
- CreateInstance(const lldb_private::ArchSpec &arch);
-
-
- DisassemblerLLVM(const lldb_private::ArchSpec &arch);
-
- virtual
- ~DisassemblerLLVM();
-
- size_t
- DecodeInstructions (const lldb_private::Address &base_addr,
- const lldb_private::DataExtractor& data,
- uint32_t data_offset,
- uint32_t num_instructions,
- bool append);
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual const char *
- GetPluginName();
-
- virtual const char *
- GetShortPluginName();
-
- virtual uint32_t
- GetPluginVersion();
-
-protected:
- bool
- IsValid() const
- {
- return m_disassembler != NULL;
- }
-
- EDDisassemblerRef m_disassembler;
- EDDisassemblerRef m_disassembler_thumb;
-};
-
-#endif // liblldb_DisassemblerLLVM_h_
Modified: lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp Thu Jun 6 19:06:43 2013
@@ -10,10 +10,26 @@
#include "DisassemblerLLVMC.h"
#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/ADT/SmallString.h"
+
#include "lldb/Core/Address.h"
#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContext.h"
@@ -33,11 +49,11 @@ public:
InstructionLLVMC (DisassemblerLLVMC &disasm,
const lldb_private::Address &address,
AddressClass addr_class) :
- Instruction(address, addr_class),
- m_is_valid(false),
- m_disasm(disasm),
- m_disasm_sp(disasm.shared_from_this()),
- m_does_branch(eLazyBoolCalculate)
+ Instruction (address, addr_class),
+ m_disasm_sp (disasm.shared_from_this()),
+ m_does_branch (eLazyBoolCalculate),
+ m_is_valid (false),
+ m_using_file_addr (false)
{
}
@@ -46,33 +62,71 @@ public:
{
}
- static void
- PadToWidth (lldb_private::StreamString &ss,
- int new_width)
+ virtual bool
+ DoesBranch ()
{
- int old_width = ss.GetSize();
-
- if (old_width < new_width)
+ if (m_does_branch == eLazyBoolCalculate)
{
- ss.Printf("%*s", new_width - old_width, "");
+ GetDisassemblerLLVMC().Lock(this, NULL);
+ DataExtractor data;
+ if (m_opcode.GetData(data))
+ {
+ bool is_alternate_isa;
+ lldb::addr_t pc = m_address.GetFileAddress();
+
+ DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
+ const uint8_t *opcode_data = data.GetDataStart();
+ const size_t opcode_data_len = data.GetByteSize();
+ llvm::MCInst inst;
+ const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+ opcode_data_len,
+ pc,
+ inst);
+ // Be conservative, if we didn't understand the instruction, say it might branch...
+ if (inst_size == 0)
+ m_does_branch = eLazyBoolYes;
+ else
+ {
+ const bool can_branch = mc_disasm_ptr->CanBranch(inst);
+ if (can_branch)
+ m_does_branch = eLazyBoolYes;
+ else
+ m_does_branch = eLazyBoolNo;
+ }
+ }
+ GetDisassemblerLLVMC().Unlock();
}
+ return m_does_branch == eLazyBoolYes;
}
-
- virtual bool
- DoesBranch () const
+
+ DisassemblerLLVMC::LLVMCDisassembler *
+ GetDisasmToUse (bool &is_alternate_isa)
{
- return m_does_branch == eLazyBoolYes;
+ is_alternate_isa = false;
+ DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+ if (llvm_disasm.m_alternate_disasm_ap.get() != NULL)
+ {
+ const AddressClass address_class = GetAddressClass ();
+
+ if (address_class == eAddressClassCodeAlternateISA)
+ {
+ is_alternate_isa = true;
+ return llvm_disasm.m_alternate_disasm_ap.get();
+ }
+ }
+ return llvm_disasm.m_disasm_ap.get();
}
virtual size_t
Decode (const lldb_private::Disassembler &disassembler,
const lldb_private::DataExtractor &data,
- uint32_t data_offset)
+ lldb::offset_t data_offset)
{
// All we have to do is read the opcode which can be easy for some
// architetures
bool got_op = false;
- const ArchSpec &arch = m_disasm.GetArchitecture();
+ DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+ const ArchSpec &arch = llvm_disasm.GetArchitecture();
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
@@ -112,23 +166,13 @@ public:
}
if (!got_op)
{
- ::LLVMDisasmContextRef disasm_context = m_disasm.m_disasm_context;
-
- bool is_altnernate_isa = false;
- if (m_disasm.m_alternate_disasm_context)
- {
- const AddressClass address_class = GetAddressClass ();
+ bool is_alternate_isa = false;
+ DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
- if (address_class == eAddressClassCodeAlternateISA)
- {
- disasm_context = m_disasm.m_alternate_disasm_context;
- is_altnernate_isa = true;
- }
- }
const llvm::Triple::ArchType machine = arch.GetMachine();
if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
{
- if (machine == llvm::Triple::thumb || is_altnernate_isa)
+ if (machine == llvm::Triple::thumb || is_alternate_isa)
{
uint32_t thumb_opcode = data.GetU16(&data_offset);
if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
@@ -154,20 +198,17 @@ public:
{
// The opcode isn't evenly sized, so we need to actually use the llvm
// disassembler to parse it and get the size.
- char out_string[512];
- m_disasm.Lock(this, NULL);
uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
- const size_t opcode_data_len = data.GetByteSize() - data_offset;
+ const size_t opcode_data_len = data.BytesLeft(data_offset);
const addr_t pc = m_address.GetFileAddress();
- const size_t inst_size = ::LLVMDisasmInstruction (disasm_context,
- opcode_data,
+ llvm::MCInst inst;
+
+ llvm_disasm.Lock(this, NULL);
+ const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
opcode_data_len,
- pc, // PC value
- out_string,
- sizeof(out_string));
- // The address lookup function could have caused us to fill in our comment
- m_comment.clear();
- m_disasm.Unlock();
+ pc,
+ inst);
+ llvm_disasm.Unlock();
if (inst_size == 0)
m_opcode.Clear();
else
@@ -202,43 +243,57 @@ public:
{
char out_string[512];
- ::LLVMDisasmContextRef disasm_context;
+ DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+
+ DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
if (address_class == eAddressClassCodeAlternateISA)
- disasm_context = m_disasm.m_alternate_disasm_context;
+ mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
else
- disasm_context = m_disasm.m_disasm_context;
+ mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
- lldb::addr_t pc = LLDB_INVALID_ADDRESS;
+ lldb::addr_t pc = m_address.GetFileAddress();
+ m_using_file_addr = true;
- if (exe_ctx)
+ const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
+ if (!data_from_file)
{
- Target *target = exe_ctx->GetTargetPtr();
- if (target)
- pc = m_address.GetLoadAddress(target);
+ if (exe_ctx)
+ {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (target)
+ {
+ const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
+ if (load_addr != LLDB_INVALID_ADDRESS)
+ {
+ pc = load_addr;
+ m_using_file_addr = false;
+ }
+ }
+ }
}
- if (pc == LLDB_INVALID_ADDRESS)
- pc = m_address.GetFileAddress();
+ llvm_disasm.Lock(this, exe_ctx);
- m_disasm.Lock(this, exe_ctx);
- uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1));
+ const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
- size_t inst_size = ::LLVMDisasmInstruction (disasm_context,
- opcode_data,
- opcode_data_len,
- pc,
- out_string,
- sizeof(out_string));
+ llvm::MCInst inst;
+ size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+ opcode_data_len,
+ pc,
+ inst);
+
+ if (inst_size > 0)
+ mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
- m_disasm.Unlock();
+ llvm_disasm.Unlock();
if (inst_size == 0)
{
m_comment.assign ("unknown opcode");
inst_size = m_opcode.GetByteSize();
StreamString mnemonic_strm;
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
switch (inst_size)
{
case 1:
@@ -270,7 +325,7 @@ public:
const uint64_t uval64 = data.GetU64(&offset);
m_opcode.SetOpcode64(uval64);
m_opcode_name.assign (".quad");
- mnemonic_strm.Printf("0x%16.16llx", uval64);
+ mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
}
break;
default:
@@ -289,17 +344,19 @@ public:
}
break;
}
- m_mnemocics.swap(mnemonic_strm.GetString());
+ m_mnemonics.swap(mnemonic_strm.GetString());
return;
}
else
{
if (m_does_branch == eLazyBoolCalculate)
{
- if (StringRepresentsBranch (out_string, strlen(out_string)))
+ const bool can_branch = mc_disasm_ptr->CanBranch(inst);
+ if (can_branch)
m_does_branch = eLazyBoolYes;
else
m_does_branch = eLazyBoolNo;
+
}
}
@@ -316,110 +373,39 @@ public:
if (matches[1].rm_so != -1)
m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
if (matches[2].rm_so != -1)
- m_mnemocics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
+ m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
}
}
}
bool
- IsValid ()
+ IsValid () const
{
return m_is_valid;
}
+ bool
+ UsingFileAddress() const
+ {
+ return m_using_file_addr;
+ }
size_t
- GetByteSize ()
+ GetByteSize () const
{
return m_opcode.GetByteSize();
}
-protected:
- bool StringRepresentsBranch (const char *data, size_t size)
+ DisassemblerLLVMC &
+ GetDisassemblerLLVMC ()
{
- const char *cursor = data;
-
- bool inWhitespace = true;
-
- while (inWhitespace && cursor < data + size)
- {
- switch (*cursor)
- {
- default:
- inWhitespace = false;
- break;
- case ' ':
- break;
- case '\t':
- break;
- }
-
- if (inWhitespace)
- ++cursor;
- }
-
- if (cursor >= data + size)
- return false;
-
- llvm::Triple::ArchType arch = m_disasm.GetArchitecture().GetMachine();
-
- switch (arch)
- {
- default:
- return false;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- switch (cursor[0])
- {
- default:
- return false;
- case 'j':
- return true;
- case 'c':
- if (cursor[1] == 'a' &&
- cursor[2] == 'l' &&
- cursor[3] == 'l')
- return true;
- else
- return false;
- }
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (cursor[0])
- {
- default:
- return false;
- case 'b':
- {
- switch (cursor[1])
- {
- default:
- return true;
- case 'f':
- case 'i':
- case 'k':
- return false;
- }
- }
- case 'c':
- {
- switch (cursor[1])
- {
- default:
- return false;
- case 'b':
- return true;
- }
- }
- }
- }
-
- return false;
+ return *(DisassemblerLLVMC *)m_disasm_sp.get();
}
+protected:
- bool m_is_valid;
- DisassemblerLLVMC &m_disasm;
DisassemblerSP m_disasm_sp; // for ownership
LazyBool m_does_branch;
+ bool m_is_valid;
+ bool m_using_file_addr;
static bool s_regex_compiled;
static ::regex_t s_regex;
@@ -428,64 +414,249 @@ protected:
bool InstructionLLVMC::s_regex_compiled = false;
::regex_t InstructionLLVMC::s_regex;
-Disassembler *
-DisassemblerLLVMC::CreateInstance (const ArchSpec &arch)
+DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
+ m_is_valid(true)
+{
+ std::string Error;
+ const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
+ if (!curr_target)
+ {
+ m_is_valid = false;
+ return;
+ }
+
+ m_instr_info_ap.reset(curr_target->createMCInstrInfo());
+ m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
+
+ std::string features_str;
+
+ m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
+ features_str));
+
+ m_asm_info_ap.reset(curr_target->createMCAsmInfo(*curr_target->createMCRegInfo(triple), triple));
+
+ if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
+ {
+ m_is_valid = false;
+ return;
+ }
+
+ m_context_ap.reset(new llvm::MCContext(*m_asm_info_ap.get(), *(m_reg_info_ap.get()), 0));
+
+ m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
+ if (m_disasm_ap.get() && m_context_ap.get())
+ {
+ llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
+ if (!RelInfo)
+ {
+ m_is_valid = false;
+ return;
+ }
+ m_disasm_ap->setupForSymbolicDisassembly(NULL,
+ DisassemblerLLVMC::SymbolLookupCallback,
+ (void *) &owner,
+ m_context_ap.get(),
+ RelInfo);
+
+ unsigned asm_printer_variant;
+ if (flavor == ~0U)
+ asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
+ else
+ {
+ asm_printer_variant = flavor;
+ }
+
+ m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
+ *m_asm_info_ap.get(),
+ *m_instr_info_ap.get(),
+ *m_reg_info_ap.get(),
+ *m_subtarget_info_ap.get()));
+ if (m_instr_printer_ap.get() == NULL)
+ {
+ m_disasm_ap.reset();
+ m_is_valid = false;
+ }
+ }
+ else
+ m_is_valid = false;
+}
+
+DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
+{
+}
+
+namespace {
+ // This is the memory object we use in GetInstruction.
+ class LLDBDisasmMemoryObject : public llvm::MemoryObject {
+ const uint8_t *m_bytes;
+ uint64_t m_size;
+ uint64_t m_base_PC;
+ public:
+ LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) :
+ m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
+
+ uint64_t getBase() const { return m_base_PC; }
+ uint64_t getExtent() const { return m_size; }
+
+ int readByte(uint64_t addr, uint8_t *byte) const {
+ if (addr - m_base_PC >= m_size)
+ return -1;
+ *byte = m_bytes[addr - m_base_PC];
+ return 0;
+ }
+ };
+} // End Anonymous Namespace
+
+uint64_t
+DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
+ size_t opcode_data_len,
+ lldb::addr_t pc,
+ llvm::MCInst &mc_inst)
+{
+ LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
+ llvm::MCDisassembler::DecodeStatus status;
+
+ uint64_t new_inst_size;
+ status = m_disasm_ap->getInstruction(mc_inst,
+ new_inst_size,
+ memory_object,
+ pc,
+ llvm::nulls(),
+ llvm::nulls());
+ if (status == llvm::MCDisassembler::Success)
+ return new_inst_size;
+ else
+ return 0;
+}
+
+uint64_t
+DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
+ char *dst,
+ size_t dst_len)
{
- std::auto_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch));
+ llvm::StringRef unused_annotations;
+ llvm::SmallString<64> inst_string;
+ llvm::raw_svector_ostream inst_stream(inst_string);
+ m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
+ inst_stream.flush();
+ const size_t output_size = std::min(dst_len - 1, inst_string.size());
+ std::memcpy(dst, inst_string.data(), output_size);
+ dst[output_size] = '\0';
- if (disasm_ap.get() && disasm_ap->IsValid())
- return disasm_ap.release();
+ return output_size;
+}
+
+bool
+DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
+{
+ return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
+}
+
+bool
+DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+{
+ llvm::Triple triple = arch.GetTriple();
+ if (flavor == NULL || strcmp (flavor, "default") == 0)
+ return true;
+ if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
+ {
+ if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
+
+Disassembler *
+DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
+{
+ if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
+ {
+ std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
+
+ if (disasm_ap.get() && disasm_ap->IsValid())
+ return disasm_ap.release();
+ }
return NULL;
}
-DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch) :
- Disassembler(arch),
+DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
+ Disassembler(arch, flavor_string),
m_exe_ctx (NULL),
m_inst (NULL),
- m_disasm_context (NULL),
- m_alternate_disasm_context (NULL)
+ m_data_from_file (false)
{
- m_disasm_context = ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(),
- (void*)this,
- /*TagType=*/1,
- NULL,
- DisassemblerLLVMC::SymbolLookupCallback);
+ if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
+ {
+ m_flavor.assign("default");
+ }
+
+ const char *triple = arch.GetTriple().getTriple().c_str();
+ unsigned flavor = ~0U;
+
+ // So far the only supported flavor is "intel" on x86. The base class will set this
+ // correctly coming in.
+ if (arch.GetTriple().getArch() == llvm::Triple::x86
+ || arch.GetTriple().getArch() == llvm::Triple::x86_64)
+ {
+ if (m_flavor == "intel")
+ {
+ flavor = 1;
+ }
+ else if (m_flavor == "att")
+ {
+ flavor = 0;
+ }
+ }
+
+ m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
+ if (!m_disasm_ap->IsValid())
+ {
+ // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
+ // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
+ m_disasm_ap.reset();
+ }
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
ArchSpec thumb_arch(arch);
- thumb_arch.GetTriple().setArchName(llvm::StringRef("thumbv7"));
+ std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
+ // Replace "arm" with "thumb" so we get all thumb variants correct
+ if (thumb_arch_name.size() > 3)
+ {
+ thumb_arch_name.erase(0,3);
+ thumb_arch_name.insert(0, "thumb");
+ }
+ else
+ {
+ thumb_arch_name = "thumbv7";
+ }
+ thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
-
- m_alternate_disasm_context = ::LLVMCreateDisasm(thumb_triple.c_str(),
- (void*)this,
- /*TagType=*/1,
- NULL,
- DisassemblerLLVMC::SymbolLookupCallback);
+ m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
+ if (!m_alternate_disasm_ap->IsValid())
+ {
+ m_disasm_ap.reset();
+ m_alternate_disasm_ap.reset();
+ }
}
}
DisassemblerLLVMC::~DisassemblerLLVMC()
{
- if (m_disasm_context)
- {
- ::LLVMDisasmDispose(m_disasm_context);
- m_disasm_context = NULL;
- }
- if (m_alternate_disasm_context)
- {
- ::LLVMDisasmDispose(m_alternate_disasm_context);
- m_alternate_disasm_context = NULL;
- }
}
size_t
DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
const DataExtractor& data,
- uint32_t data_offset,
- uint32_t num_instructions,
- bool append)
+ lldb::offset_t data_offset,
+ size_t num_instructions,
+ bool append,
+ bool data_from_file)
{
if (!append)
m_instruction_list.Clear();
@@ -493,6 +664,7 @@ DisassemblerLLVMC::DecodeInstructions (c
if (!IsValid())
return 0;
+ m_data_from_file = data_from_file;
uint32_t data_cursor = data_offset;
const size_t data_byte_size = data.GetByteSize();
uint32_t instructions_parsed = 0;
@@ -503,7 +675,7 @@ DisassemblerLLVMC::DecodeInstructions (c
AddressClass address_class = eAddressClassCode;
- if (m_alternate_disasm_context)
+ if (m_alternate_disasm_ap.get() != NULL)
address_class = inst_addr.GetAddressClass ();
InstructionSP inst_sp(new InstructionLLVMC(*this,
@@ -531,7 +703,7 @@ void
DisassemblerLLVMC::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
+ "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.",
CreateInstance);
llvm::InitializeAllTargetInfos();
@@ -547,16 +719,11 @@ DisassemblerLLVMC::Terminate()
}
-const char *
+ConstString
DisassemblerLLVMC::GetPluginNameStatic()
{
- return "llvm-mc";
-}
-
-const char *
-DisassemblerLLVMC::GetPluginDescriptionStatic()
-{
- return "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.";
+ static ConstString g_name("llvm-mc");
+ return g_name;
}
int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
@@ -612,36 +779,33 @@ const char *DisassemblerLLVMC::SymbolLoo
if (m_exe_ctx && m_inst)
{
//std::string remove_this_prior_to_checkin;
- Address reference_address;
-
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
-
- if (target && !target->GetSectionLoadList().IsEmpty())
- target->GetSectionLoadList().ResolveLoadAddress(value, reference_address);
- else
+ Address value_so_addr;
+ if (m_inst->UsingFileAddress())
{
ModuleSP module_sp(m_inst->GetAddress().GetModule());
if (module_sp)
- module_sp->ResolveFileAddress(value, reference_address);
+ module_sp->ResolveFileAddress(value, value_so_addr);
}
-
- if (reference_address.IsValid() && reference_address.GetSection())
+ else if (target && !target->GetSectionLoadList().IsEmpty())
+ {
+ target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
+ }
+
+ if (value_so_addr.IsValid() && value_so_addr.GetSection())
{
StreamString ss;
- reference_address.Dump (&ss,
- target,
- Address::DumpStyleResolvedDescriptionNoModule,
- Address::DumpStyleSectionNameOffset);
+ value_so_addr.Dump (&ss,
+ target,
+ Address::DumpStyleResolvedDescriptionNoModule,
+ Address::DumpStyleSectionNameOffset);
if (!ss.GetString().empty())
{
- //remove_this_prior_to_checkin = ss.GetString();
- //if (*type_ptr)
m_inst->AppendComment(ss.GetString());
}
}
- //printf ("DisassemblerLLVMC::SymbolLookup (value=0x%16.16llx, type=%llu, pc=0x%16.16llx, name=\"%s\") m_exe_ctx=%p, m_inst=%p\n", value, *type_ptr, pc, remove_this_prior_to_checkin.c_str(), m_exe_ctx, m_inst);
}
}
@@ -653,15 +817,9 @@ const char *DisassemblerLLVMC::SymbolLoo
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+ConstString
DisassemblerLLVMC::GetPluginName()
{
- return "DisassemblerLLVMC";
-}
-
-const char *
-DisassemblerLLVMC::GetShortPluginName()
-{
return GetPluginNameStatic();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h Thu Jun 6 19:06:43 2013
@@ -10,9 +10,23 @@
#ifndef liblldb_DisassemblerLLVMC_h_
#define liblldb_DisassemblerLLVMC_h_
+#include <string>
#include "llvm-c/Disassembler.h"
+// Opaque references to C++ Objects in LLVM's MC.
+namespace llvm
+{
+ class MCContext;
+ class MCInst;
+ class MCInstrInfo;
+ class MCRegisterInfo;
+ class MCDisassembler;
+ class MCInstPrinter;
+ class MCAsmInfo;
+ class MCSubtargetInfo;
+}
+
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/PluginManager.h"
@@ -22,6 +36,34 @@ class InstructionLLVMC;
class DisassemblerLLVMC : public lldb_private::Disassembler
{
+ // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), and there's a bit of goo to set up and own
+ // in the MC disassembler world, I added this class to manage the actual disassemblers.
+ class LLVMCDisassembler
+ {
+ public:
+ LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner);
+
+ ~LLVMCDisassembler();
+
+ uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
+ uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
+ bool CanBranch (llvm::MCInst &mc_inst);
+ bool IsValid()
+ {
+ return m_is_valid;
+ }
+
+ private:
+ bool m_is_valid;
+ std::unique_ptr<llvm::MCContext> m_context_ap;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info_ap;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_ap;
+ std::unique_ptr<llvm::MCInstrInfo> m_instr_info_ap;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_ap;
+ std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_ap;
+ std::unique_ptr<llvm::MCDisassembler> m_disasm_ap;
+ };
+
public:
//------------------------------------------------------------------
// Static Functions
@@ -32,47 +74,44 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
- static const char *
- GetPluginDescriptionStatic();
-
static lldb_private::Disassembler *
- CreateInstance(const lldb_private::ArchSpec &arch);
-
-
- DisassemblerLLVMC(const lldb_private::ArchSpec &arch);
+ CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
+
+ DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
virtual
~DisassemblerLLVMC();
- size_t
+ virtual size_t
DecodeInstructions (const lldb_private::Address &base_addr,
const lldb_private::DataExtractor& data,
- uint32_t data_offset,
- uint32_t num_instructions,
- bool append);
+ lldb::offset_t data_offset,
+ size_t num_instructions,
+ bool append,
+ bool data_from_file);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
protected:
friend class InstructionLLVMC;
+ virtual bool
+ FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
+
bool
IsValid()
{
- return (m_disasm_context != NULL);
+ return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
}
int OpInfo(uint64_t PC,
@@ -117,8 +156,10 @@ protected:
const lldb_private::ExecutionContext *m_exe_ctx;
InstructionLLVMC *m_inst;
lldb_private::Mutex m_mutex;
- ::LLVMDisasmContextRef m_disasm_context;
- ::LLVMDisasmContextRef m_alternate_disasm_context;
+ bool m_data_from_file;
+
+ std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
+ std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
};
#endif // liblldb_DisassemblerLLVM_h_
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp Thu Jun 6 19:06:43 2013
@@ -7,21 +7,26 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
+
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
+#include "lldb/Host/Symbols.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
-#include "lldb/Target/StackFrame.h"
+#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
#include "DynamicLoaderDarwinKernel.h"
@@ -36,10 +41,91 @@
using namespace lldb;
using namespace lldb_private;
-/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here.
-/// I am putting it here so I can invoke it in the Trampoline code here, but
-/// it should be moved to the ObjC Runtime support when it is set up.
+// Progressively greater amounts of scanning we will allow
+// For some targets very early in startup, we can't do any random reads of memory or we can crash the device
+// so a setting is needed that can completely disable the KASLR scans.
+
+enum KASLRScanType
+{
+ eKASLRScanNone = 0, // No reading into the inferior at all
+ eKASLRScanLowgloAddresses, // Check one word of memory for a possible kernel addr, then see if a kernel is there
+ eKASLRScanNearPC, // Scan backwards from the current $pc looking for kernel; checking at 96 locations total
+ eKASLRScanExhaustiveScan // Scan through the entire possible kernel address range looking for a kernel
+};
+
+OptionEnumValueElement
+g_kaslr_kernel_scan_enum_values[] =
+{
+ { eKASLRScanNone, "none", "Do not read memory looking for a Darwin kernel when attaching." },
+ { eKASLRScanLowgloAddresses, "basic", "Check for the Darwin kernel's load addr in the lowglo page (boot-args=debug) only." },
+ { eKASLRScanNearPC, "fast-scan", "Scan near the pc value on attach to find the Darwin kernel's load address."},
+ { eKASLRScanExhaustiveScan, "exhaustive-scan", "Scan through the entire potential address range of Darwin kernel (only on 32-bit targets)."},
+ { 0, NULL, NULL }
+};
+
+static PropertyDefinition
+g_properties[] =
+{
+ { "load-kexts" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Automatically loads kext images when attaching to a kernel." },
+ { "scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, NULL, g_kaslr_kernel_scan_enum_values, "Control how many reads lldb will make while searching for a Darwin kernel on attach." },
+ { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
+};
+
+enum {
+ ePropertyLoadKexts,
+ ePropertyScanType
+};
+
+class DynamicLoaderDarwinKernelProperties : public Properties
+{
+public:
+
+ static ConstString &
+ GetSettingName ()
+ {
+ static ConstString g_setting_name("darwin-kernel");
+ return g_setting_name;
+ }
+
+ DynamicLoaderDarwinKernelProperties() :
+ Properties ()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ virtual
+ ~DynamicLoaderDarwinKernelProperties()
+ {
+ }
+
+ bool
+ GetLoadKexts() const
+ {
+ const uint32_t idx = ePropertyLoadKexts;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ }
+
+ KASLRScanType
+ GetScanType() const
+ {
+ const uint32_t idx = ePropertyScanType;
+ return (KASLRScanType) m_collection_sp->GetPropertyAtIndexAsEnumeration (NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+};
+
+typedef std::shared_ptr<DynamicLoaderDarwinKernelProperties> DynamicLoaderDarwinKernelPropertiesSP;
+
+static const DynamicLoaderDarwinKernelPropertiesSP &
+GetGlobalProperties()
+{
+ static DynamicLoaderDarwinKernelPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset (new DynamicLoaderDarwinKernelProperties ());
+ return g_settings_sp;
+}
//----------------------------------------------------------------------
// Create an instance of this class. This function is filled into
@@ -49,57 +135,339 @@ using namespace lldb_private;
DynamicLoader *
DynamicLoaderDarwinKernel::CreateInstance (Process* process, bool force)
{
- bool create = force;
- if (!create)
+ if (!force)
{
+ // If the user provided an executable binary and it is not a kernel,
+ // this plugin should not create an instance.
Module* exe_module = process->GetTarget().GetExecutableModulePointer();
if (exe_module)
{
ObjectFile *object_file = exe_module->GetObjectFile();
if (object_file)
{
- create = (object_file->GetStrata() == ObjectFile::eStrataKernel);
+ if (object_file->GetStrata() != ObjectFile::eStrataKernel)
+ {
+ return NULL;
+ }
}
}
-
- if (create)
+
+ // If the target's architecture does not look like an Apple environment,
+ // this plugin should not create an instance.
+ const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+ switch (triple_ref.getOS())
{
- const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
- switch (triple_ref.getOS())
- {
- case llvm::Triple::Darwin:
- case llvm::Triple::MacOSX:
- case llvm::Triple::IOS:
- create = triple_ref.getVendor() == llvm::Triple::Apple;
- break;
- default:
- create = false;
- break;
- }
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS:
+ if (triple_ref.getVendor() != llvm::Triple::Apple)
+ {
+ return NULL;
+ }
+ break;
+ // If we have triple like armv7-unknown-unknown, we should try looking for a Darwin kernel.
+ case llvm::Triple::UnknownOS:
+ break;
+ default:
+ return NULL;
+ break;
}
}
-
- if (create)
+
+ // At this point if there is an ExecutableModule, it is a kernel and the Target is some variant of an Apple system.
+ // If the Process hasn't provided the kernel load address, we need to look around in memory to find it.
+
+ addr_t kernel_load_address = SearchForDarwinKernel (process);
+ if (kernel_load_address != LLDB_INVALID_ADDRESS)
{
process->SetCanJIT(false);
- return new DynamicLoaderDarwinKernel (process);
+ return new DynamicLoaderDarwinKernel (process, kernel_load_address);
}
return NULL;
}
+lldb::addr_t
+DynamicLoaderDarwinKernel::SearchForDarwinKernel (Process *process)
+{
+ addr_t kernel_load_address = process->GetImageInfoAddress();
+ if (kernel_load_address == LLDB_INVALID_ADDRESS)
+ {
+ kernel_load_address = SearchForKernelAtSameLoadAddr (process);
+ if (kernel_load_address == LLDB_INVALID_ADDRESS)
+ {
+ kernel_load_address = SearchForKernelWithDebugHints (process);
+ if (kernel_load_address == LLDB_INVALID_ADDRESS)
+ {
+ kernel_load_address = SearchForKernelNearPC (process);
+ if (kernel_load_address == LLDB_INVALID_ADDRESS)
+ {
+ kernel_load_address = SearchForKernelViaExhaustiveSearch (process);
+ }
+ }
+ }
+ }
+ return kernel_load_address;
+}
+
+//----------------------------------------------------------------------
+// Check if the kernel binary is loaded in memory without a slide.
+// First verify that the ExecutableModule is a kernel before we proceed.
+// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
+//----------------------------------------------------------------------
+lldb::addr_t
+DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr (Process *process)
+{
+ Module *exe_module = process->GetTarget().GetExecutableModulePointer();
+ if (exe_module == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ ObjectFile *exe_objfile = exe_module->GetObjectFile();
+ if (exe_objfile == NULL)
+ return LLDB_INVALID_ADDRESS;
+
+ if (exe_objfile->GetType() != ObjectFile::eTypeExecutable || exe_objfile->GetStrata() != ObjectFile::eStrataKernel)
+ return LLDB_INVALID_ADDRESS;
+
+ if (!exe_objfile->GetHeaderAddress().IsValid())
+ return LLDB_INVALID_ADDRESS;
+
+ if (CheckForKernelImageAtAddress (exe_objfile->GetHeaderAddress().GetFileAddress(), process) == exe_module->GetUUID())
+ return exe_objfile->GetHeaderAddress().GetFileAddress();
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+//----------------------------------------------------------------------
+// If the debug flag is included in the boot-args nvram setting, the kernel's load address
+// will be noted in the lowglo page at a fixed address
+// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
+//----------------------------------------------------------------------
+lldb::addr_t
+DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints (Process *process)
+{
+ if (GetGlobalProperties()->GetScanType() == eKASLRScanNone)
+ return LLDB_INVALID_ADDRESS;
+
+ Error read_err;
+ addr_t addr = LLDB_INVALID_ADDRESS;
+ if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
+ {
+ addr = process->ReadUnsignedIntegerFromMemory (0xffffff8000002010ULL, 8, LLDB_INVALID_ADDRESS, read_err);
+ }
+ else
+ {
+ addr = process->ReadUnsignedIntegerFromMemory (0xffff0110, 4, LLDB_INVALID_ADDRESS, read_err);
+ }
+
+ if (addr == 0)
+ addr = LLDB_INVALID_ADDRESS;
+
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ if (CheckForKernelImageAtAddress (addr, process).IsValid())
+ return addr;
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+//----------------------------------------------------------------------
+// If the kernel is currently executing when lldb attaches, and we don't have
+// a better way of finding the kernel's load address, try searching backwards
+// from the current pc value looking for the kernel's Mach header in memory.
+// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
+//----------------------------------------------------------------------
+lldb::addr_t
+DynamicLoaderDarwinKernel::SearchForKernelNearPC (Process *process)
+{
+ if (GetGlobalProperties()->GetScanType() == eKASLRScanNone
+ || GetGlobalProperties()->GetScanType() == eKASLRScanLowgloAddresses)
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ ThreadSP thread = process->GetThreadList().GetSelectedThread ();
+ if (thread.get() == NULL)
+ return LLDB_INVALID_ADDRESS;
+ addr_t pc = thread->GetRegisterContext ()->GetPC(LLDB_INVALID_ADDRESS);
+
+ if (pc == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t kernel_range_low;
+ if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
+ {
+ kernel_range_low = 1ULL << 63;
+ }
+ else
+ {
+ kernel_range_low = 1ULL << 31;
+ }
+
+ // Outside the normal kernel address range, this is probably userland code running right now
+ if (pc < kernel_range_low)
+ return LLDB_INVALID_ADDRESS;
+
+ // The kernel will load at at one megabyte boundary (0x100000), or at that boundary plus
+ // an offset of one page (0x1000) or two, depending on the device.
+
+ // Round the current pc down to the nearest one megabyte boundary - the place where we will start searching.
+ addr_t addr = pc & ~0xfffff;
+
+ int i = 0;
+ while (i < 32 && pc >= kernel_range_low)
+ {
+ if (CheckForKernelImageAtAddress (addr, process).IsValid())
+ return addr;
+ if (CheckForKernelImageAtAddress (addr + 0x1000, process).IsValid())
+ return addr + 0x1000;
+ if (CheckForKernelImageAtAddress (addr + 0x2000, process).IsValid())
+ return addr + 0x2000;
+ i++;
+ addr -= 0x100000;
+ }
+
+ return LLDB_INVALID_ADDRESS;
+}
+
+//----------------------------------------------------------------------
+// Scan through the valid address range for a kernel binary.
+// This is uselessly slow in 64-bit environments so we don't even try it.
+// This scan is not enabled by default even for 32-bit targets.
+// Returns the address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
+//----------------------------------------------------------------------
+lldb::addr_t
+DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch (Process *process)
+{
+ if (GetGlobalProperties()->GetScanType() != eKASLRScanExhaustiveScan)
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ addr_t kernel_range_low, kernel_range_high;
+ if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
+ {
+ kernel_range_low = 1ULL << 63;
+ kernel_range_high = UINT64_MAX;
+ }
+ else
+ {
+ kernel_range_low = 1ULL << 31;
+ kernel_range_high = UINT32_MAX;
+ }
+
+ // Stepping through memory at one-megabyte resolution looking for a kernel
+ // rarely works (fast enough) with a 64-bit address space -- for now, let's
+ // not even bother. We may be attaching to something which *isn't* a kernel
+ // and we don't want to spin for minutes on-end looking for a kernel.
+ if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8)
+ return LLDB_INVALID_ADDRESS;
+
+ addr_t addr = kernel_range_low;
+
+ while (addr >= kernel_range_low && addr < kernel_range_high)
+ {
+ if (CheckForKernelImageAtAddress (addr, process).IsValid())
+ return addr;
+ if (CheckForKernelImageAtAddress (addr + 0x1000, process).IsValid())
+ return addr + 0x1000;
+ if (CheckForKernelImageAtAddress (addr + 0x2000, process).IsValid())
+ return addr + 0x2000;
+ addr += 0x100000;
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
+//----------------------------------------------------------------------
+// Given an address in memory, look to see if there is a kernel image at that
+// address.
+// Returns a UUID; if a kernel was not found at that address, UUID.IsValid() will be false.
+//----------------------------------------------------------------------
+lldb_private::UUID
+DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Process *process)
+{
+ if (addr == LLDB_INVALID_ADDRESS)
+ return UUID();
+
+ // First try a quick test -- read the first 4 bytes and see if there is a valid Mach-O magic field there
+ // (the first field of the mach_header/mach_header_64 struct).
+
+ Error read_error;
+ uint64_t result = process->ReadUnsignedIntegerFromMemory (addr, 4, LLDB_INVALID_ADDRESS, read_error);
+ if (result != llvm::MachO::HeaderMagic64
+ && result != llvm::MachO::HeaderMagic32
+ && result != llvm::MachO::HeaderMagic32Swapped
+ && result != llvm::MachO::HeaderMagic64Swapped)
+ {
+ return UUID();
+ }
+
+ // Read the mach header and see whether it looks like a kernel
+ llvm::MachO::mach_header header;
+ if (process->DoReadMemory (addr, &header, sizeof(header), read_error) != sizeof(header))
+ return UUID();
+
+ if (header.magic == llvm::MachO::HeaderMagic32Swapped ||
+ header.magic == llvm::MachO::HeaderMagic64Swapped)
+ {
+ header.magic = llvm::ByteSwap_32(header.magic);
+ header.cputype = llvm::ByteSwap_32(header.cputype);
+ header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype);
+ header.filetype = llvm::ByteSwap_32(header.filetype);
+ header.ncmds = llvm::ByteSwap_32(header.ncmds);
+ header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds);
+ header.flags = llvm::ByteSwap_32(header.flags);
+ }
+
+ // A kernel is an executable which does not have the dynamic link object flag set.
+ if (header.filetype == llvm::MachO::HeaderFileTypeExecutable
+ && (header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
+ {
+ // Create a full module to get the UUID
+ ModuleSP memory_module_sp = process->ReadModuleFromMemory (FileSpec ("temp_mach_kernel", false), addr);
+ if (!memory_module_sp.get())
+ return UUID();
+
+ ObjectFile *exe_objfile = memory_module_sp->GetObjectFile();
+ if (exe_objfile == NULL)
+ return UUID();
+
+ if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
+ {
+ ArchSpec kernel_arch (eArchTypeMachO, header.cputype, header.cpusubtype);
+ if (!process->GetTarget().GetArchitecture().IsCompatibleMatch(kernel_arch))
+ {
+ process->GetTarget().SetArchitecture (kernel_arch);
+ }
+ return memory_module_sp->GetUUID();
+ }
+ }
+
+ return UUID();
+}
+
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
-DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process) :
+DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process, lldb::addr_t kernel_addr) :
DynamicLoader(process),
+ m_kernel_load_address (kernel_addr),
m_kernel(),
m_kext_summary_header_ptr_addr (),
m_kext_summary_header_addr (),
m_kext_summary_header (),
- m_kext_summaries(),
+ m_known_kexts (),
m_mutex(Mutex::eMutexTypeRecursive),
m_break_id (LLDB_INVALID_BREAK_ID)
{
+ PlatformSP platform_sp(Platform::FindPlugin (process, PlatformDarwinKernel::GetPluginNameStatic ()));
+ // Only select the darwin-kernel Platform if we've been asked to load kexts.
+ // It can take some time to scan over all of the kext info.plists and that
+ // shouldn't be done if kext loading is explicitly disabled.
+ if (platform_sp.get() && GetGlobalProperties()->GetLoadKexts())
+ {
+ process->GetTarget().SetPlatform (platform_sp);
+ }
}
//----------------------------------------------------------------------
@@ -156,152 +524,480 @@ DynamicLoaderDarwinKernel::Clear (bool c
if (clear_process)
m_process = NULL;
- m_kernel.Clear(false);
+ m_kernel.Clear();
+ m_known_kexts.clear();
m_kext_summary_header_ptr_addr.Clear();
m_kext_summary_header_addr.Clear();
- m_kext_summaries.clear();
m_break_id = LLDB_INVALID_BREAK_ID;
}
bool
-DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageAtFileAddress (Process *process)
+DynamicLoaderDarwinKernel::KextImageInfo::LoadImageAtFileAddress (Process *process)
{
if (IsLoaded())
return true;
- if (module_sp)
+ if (m_module_sp)
{
bool changed = false;
- if (module_sp->SetLoadAddress (process->GetTarget(), 0, changed))
- load_process_stop_id = process->GetStopID();
+ if (m_module_sp->SetLoadAddress (process->GetTarget(), 0, changed))
+ m_load_process_stop_id = process->GetStopID();
}
return false;
}
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetModule (ModuleSP module_sp)
+{
+ m_module_sp = module_sp;
+ if (module_sp.get() && module_sp->GetObjectFile())
+ {
+ if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable
+ && module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel)
+ {
+ m_kernel_image = true;
+ }
+ else
+ {
+ m_kernel_image = false;
+ }
+ }
+}
+
+ModuleSP
+DynamicLoaderDarwinKernel::KextImageInfo::GetModule ()
+{
+ return m_module_sp;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetLoadAddress (addr_t load_addr)
+{
+ m_load_address = load_addr;
+}
+
+addr_t
+DynamicLoaderDarwinKernel::KextImageInfo::GetLoadAddress () const
+{
+ return m_load_address;
+}
+
+uint64_t
+DynamicLoaderDarwinKernel::KextImageInfo::GetSize () const
+{
+ return m_size;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetSize (uint64_t size)
+{
+ m_size = size;
+}
+
+uint32_t
+DynamicLoaderDarwinKernel::KextImageInfo::GetProcessStopId () const
+{
+ return m_load_process_stop_id;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetProcessStopId (uint32_t stop_id)
+{
+ m_load_process_stop_id = stop_id;
+}
+
+bool
+DynamicLoaderDarwinKernel::KextImageInfo::operator== (const KextImageInfo &rhs)
+{
+ if (m_uuid.IsValid() || rhs.GetUUID().IsValid())
+ {
+ if (m_uuid == rhs.GetUUID())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ if (m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress())
+ return true;
+
+ return false;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetName (const char *name)
+{
+ m_name = name;
+}
+
+std::string
+DynamicLoaderDarwinKernel::KextImageInfo::GetName () const
+{
+ return m_name;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetUUID (const UUID &uuid)
+{
+ m_uuid = uuid;
+}
+
+UUID
+DynamicLoaderDarwinKernel::KextImageInfo::GetUUID () const
+{
+ return m_uuid;
+}
+
+// Given the m_load_address from the kext summaries, and a UUID, try to create an in-memory
+// Module at that address. Require that the MemoryModule have a matching UUID and detect
+// if this MemoryModule is a kernel or a kext.
+//
+// Returns true if m_memory_module_sp is now set to a valid Module.
+
+bool
+DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule (Process *process)
+{
+ if (m_memory_module_sp.get() != NULL)
+ return true;
+ if (m_load_address == LLDB_INVALID_ADDRESS)
+ return false;
+
+ FileSpec file_spec;
+ file_spec.SetFile (m_name.c_str(), false);
+
+ ModuleSP memory_module_sp = process->ReadModuleFromMemory (file_spec, m_load_address);
+
+ if (memory_module_sp.get() == NULL)
+ return false;
+
+ bool is_kernel = false;
+ if (memory_module_sp->GetObjectFile())
+ {
+ if (memory_module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable
+ && memory_module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel)
+ {
+ is_kernel = true;
+ }
+ else if (memory_module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeSharedLibrary)
+ {
+ is_kernel = false;
+ }
+ }
+
+ // If this is a kext, and the kernel specified what UUID we should find at this
+ // load address, require that the memory module have a matching UUID or something
+ // has gone wrong and we should discard it.
+ if (m_uuid.IsValid())
+ {
+ if (m_uuid != memory_module_sp->GetUUID())
+ {
+ return false;
+ }
+ }
+
+ // If the in-memory Module has a UUID, let's use that.
+ if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid())
+ {
+ m_uuid = memory_module_sp->GetUUID();
+ }
+
+ m_memory_module_sp = memory_module_sp;
+ m_kernel_image = is_kernel;
+ if (is_kernel)
+ {
+ if (memory_module_sp->GetArchitecture().IsValid())
+ {
+ process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture());
+ }
+ if (m_uuid.IsValid())
+ {
+ Module* exe_module = process->GetTarget().GetExecutableModulePointer();
+ if (exe_module && exe_module->GetUUID().IsValid())
+ {
+ if (m_uuid != exe_module->GetUUID())
+ {
+ Stream *s = &process->GetTarget().GetDebugger().GetOutputStream();
+ if (s)
+ {
+ s->Printf ("warning: Host-side kernel file has Mach-O UUID of %s but remote kernel has a UUID of %s -- a mismatched kernel file will result in a poor debugger experience.\n",
+ exe_module->GetUUID().GetAsString().c_str(),
+ m_uuid.GetAsString().c_str());
+ s->Flush ();
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
+DynamicLoaderDarwinKernel::KextImageInfo::IsKernel () const
+{
+ return m_kernel_image == true;
+}
+
+void
+DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel (bool is_kernel)
+{
+ m_kernel_image = is_kernel;
+}
+
bool
-DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::LoadImageUsingMemoryModule (Process *process)
+DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule (Process *process)
{
if (IsLoaded())
return true;
- bool uuid_is_valid = uuid.IsValid();
Target &target = process->GetTarget();
- ModuleSP memory_module_sp;
- // Use the memory module as the module if we have one...
- if (address != LLDB_INVALID_ADDRESS)
- {
- FileSpec file_spec;
- if (module_sp)
- file_spec = module_sp->GetFileSpec();
- else
- file_spec.SetFile (name, false);
-
- memory_module_sp = process->ReadModuleFromMemory (file_spec, address, false, false);
- if (memory_module_sp && !uuid_is_valid)
+
+ // If we don't have / can't create a memory module for this kext, don't try to load it - we won't
+ // have the correct segment load addresses.
+ if (!ReadMemoryModule (process))
+ {
+ return false;
+ }
+
+ bool uuid_is_valid = m_uuid.IsValid();
+
+ if (IsKernel() && uuid_is_valid && m_memory_module_sp.get())
+ {
+ Stream *s = &target.GetDebugger().GetOutputStream();
+ if (s)
{
- uuid = memory_module_sp->GetUUID();
- uuid_is_valid = uuid.IsValid();
+ s->Printf ("Kernel UUID: %s\n", m_memory_module_sp->GetUUID().GetAsString().c_str());
+ s->Printf ("Load Address: 0x%" PRIx64 "\n", m_load_address);
}
}
- if (!module_sp)
+ if (!m_module_sp)
{
- if (uuid_is_valid)
+ // See if the kext has already been loaded into the target, probably by the user doing target modules add.
+ const ModuleList &target_images = target.GetImages();
+ m_module_sp = target_images.FindModule(m_uuid);
+
+ // Search for the kext on the local filesystem via the UUID
+ if (!m_module_sp && uuid_is_valid)
{
- ModuleList &target_images = target.GetImages();
- module_sp = target_images.FindModule(uuid);
-
- if (!module_sp)
+ ModuleSpec module_spec;
+ module_spec.GetUUID() = m_uuid;
+ module_spec.GetArchitecture() = target.GetArchitecture();
+
+ // For the kernel, we really do need an on-disk file copy of the binary to do anything useful.
+ // This will force a clal to
+ if (IsKernel())
+ {
+ if (Symbols::DownloadObjectAndSymbolFile (module_spec, true))
+ {
+ if (module_spec.GetFileSpec().Exists())
+ {
+ m_module_sp.reset(new Module (module_spec.GetFileSpec(), target.GetArchitecture()));
+ if (m_module_sp.get() && m_module_sp->MatchesModuleSpec (module_spec))
+ {
+ ModuleList loaded_module_list;
+ loaded_module_list.Append (m_module_sp);
+ target.ModulesDidLoad (loaded_module_list);
+ }
+ }
+ }
+ }
+
+ // If the current platform is PlatformDarwinKernel, create a ModuleSpec with the filename set
+ // to be the bundle ID for this kext, e.g. "com.apple.filesystems.msdosfs", and ask the platform
+ // to find it.
+ PlatformSP platform_sp (target.GetPlatform());
+ if (platform_sp)
+ {
+ ConstString platform_name (platform_sp->GetPluginName());
+ static ConstString g_platform_name (PlatformDarwinKernel::GetPluginNameStatic());
+ if (platform_name == g_platform_name)
+ {
+ ModuleSpec kext_bundle_module_spec(module_spec);
+ FileSpec kext_filespec(m_name.c_str(), false);
+ kext_bundle_module_spec.GetFileSpec() = kext_filespec;
+ platform_sp->GetSharedModule (kext_bundle_module_spec, m_module_sp, &target.GetExecutableSearchPaths(), NULL, NULL);
+ }
+ }
+
+ // Ask the Target to find this file on the local system, if possible.
+ // This will search in the list of currently-loaded files, look in the
+ // standard search paths on the system, and on a Mac it will try calling
+ // the DebugSymbols framework with the UUID to find the binary via its
+ // search methods.
+ if (!m_module_sp)
+ {
+ m_module_sp = target.GetSharedModule (module_spec);
+ }
+
+ if (IsKernel() && !m_module_sp)
+ {
+ Stream *s = &target.GetDebugger().GetOutputStream();
+ if (s)
+ {
+ s->Printf ("WARNING: Unable to locate kernel binary on the debugger system.\n");
+ }
+ }
+ }
+
+ // If we managed to find a module, append it to the target's list of images.
+ // If we also have a memory module, require that they have matching UUIDs
+ if (m_module_sp)
+ {
+ bool uuid_match_ok = true;
+ if (m_memory_module_sp)
{
- ModuleSpec module_spec;
- module_spec.GetUUID() = uuid;
- module_sp = target.GetSharedModule (module_spec);
+ if (m_module_sp->GetUUID() != m_memory_module_sp->GetUUID())
+ {
+ uuid_match_ok = false;
+ }
+ }
+ if (uuid_match_ok)
+ {
+ target.GetImages().AppendIfNeeded(m_module_sp);
+ if (IsKernel() && target.GetExecutableModulePointer() != m_module_sp.get())
+ {
+ target.SetExecutableModule (m_module_sp, false);
+ }
}
}
}
+ if (!m_module_sp && !IsKernel() && m_uuid.IsValid() && !m_name.empty())
+ {
+ Stream *s = &target.GetDebugger().GetOutputStream();
+ if (s)
+ {
+ s->Printf ("warning: Can't find binary/dSYM for %s (%s)\n",
+ m_name.c_str(), m_uuid.GetAsString().c_str());
+ }
+ }
+
+ static ConstString g_section_name_LINKEDIT ("__LINKEDIT");
- if (memory_module_sp)
+ if (m_memory_module_sp && m_module_sp)
{
- // Someone already supplied a file, make sure it is the right one.
- if (module_sp)
+ if (m_module_sp->GetUUID() == m_memory_module_sp->GetUUID())
{
- if (module_sp->GetUUID() == memory_module_sp->GetUUID())
+ ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile();
+ ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile();
+
+ if (memory_object_file && ondisk_object_file)
{
- ObjectFile *ondisk_object_file = module_sp->GetObjectFile();
- ObjectFile *memory_object_file = memory_module_sp->GetObjectFile();
- if (memory_object_file && ondisk_object_file)
+ // The memory_module for kexts may have an invalid __LINKEDIT seg; skip it.
+ const bool ignore_linkedit = !IsKernel ();
+
+ SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
+ SectionList *memory_section_list = memory_object_file->GetSectionList ();
+ if (memory_section_list && ondisk_section_list)
{
- SectionList *ondisk_section_list = ondisk_object_file->GetSectionList ();
- SectionList *memory_section_list = memory_object_file->GetSectionList ();
- if (memory_section_list && ondisk_section_list)
+ const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
+ // There may be CTF sections in the memory image so we can't
+ // always just compare the number of sections (which are actually
+ // segments in mach-o parlance)
+ uint32_t sect_idx = 0;
+
+ // Use the memory_module's addresses for each section to set the
+ // file module's load address as appropriate. We don't want to use
+ // a single slide value for the entire kext - different segments may
+ // be slid different amounts by the kext loader.
+
+ uint32_t num_sections_loaded = 0;
+ for (sect_idx=0; sect_idx<num_ondisk_sections; ++sect_idx)
{
- const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
- // There may be CTF sections in the memory image so we can't
- // always just compare the number of sections (which are actually
- // segments in mach-o parlance)
- uint32_t sect_idx = 0;
-
-
- // We now iterate through all sections in the file module
- // and look to see if the memory module has a load address
- // for that section.
- uint32_t num_sections_loaded = 0;
- for (sect_idx=0; sect_idx<num_ondisk_sections; ++sect_idx)
+ SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx));
+ if (ondisk_section_sp)
{
- SectionSP ondisk_section_sp(ondisk_section_list->GetSectionAtIndex(sect_idx));
- if (ondisk_section_sp)
+ // Don't ever load __LINKEDIT as it may or may not be actually
+ // mapped into memory and there is no current way to tell.
+ // I filed rdar://problem/12851706 to track being able to tell
+ // if the __LINKEDIT is actually mapped, but until then, we need
+ // to not load the __LINKEDIT
+ if (ignore_linkedit && ondisk_section_sp->GetName() == g_section_name_LINKEDIT)
+ continue;
+
+ const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
+ if (memory_section)
{
- const Section *memory_section = memory_section_list->FindSectionByName(ondisk_section_sp->GetName()).get();
- if (memory_section)
- {
- target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
- ++num_sections_loaded;
- }
+ target.GetSectionLoadList().SetSectionLoadAddress (ondisk_section_sp, memory_section->GetFileAddress());
+ ++num_sections_loaded;
}
}
- if (num_sections_loaded > 0)
- load_process_stop_id = process->GetStopID();
- else
- module_sp.reset(); // No sections were loaded
}
+ if (num_sections_loaded > 0)
+ m_load_process_stop_id = process->GetStopID();
else
- module_sp.reset(); // One or both section lists
+ m_module_sp.reset(); // No sections were loaded
}
else
- module_sp.reset(); // One or both object files missing
+ m_module_sp.reset(); // One or both section lists
}
else
- module_sp.reset(); // UUID mismatch
- }
-
- // Use the memory module as the module if we didn't like the file
- // module we either found or were supplied with
- if (!module_sp)
- {
- module_sp = memory_module_sp;
- // Load the memory image in the target as all adresses are already correct
- bool changed = false;
- target.GetImages().Append (memory_module_sp);
- if (module_sp->SetLoadAddress (target, 0, changed))
- load_process_stop_id = process->GetStopID();
+ m_module_sp.reset(); // One or both object files missing
}
+ else
+ m_module_sp.reset(); // UUID mismatch
}
+
bool is_loaded = IsLoaded();
- if (so_address.IsValid())
+ if (is_loaded && m_module_sp && IsKernel())
{
- if (is_loaded)
- so_address.SetLoadAddress (address, &target);
- else
- target.GetImages().ResolveFileAddress (address, so_address);
-
+ Stream *s = &target.GetDebugger().GetOutputStream();
+ if (s)
+ {
+ ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
+ if (kernel_object_file)
+ {
+ addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
+ if (m_load_address != LLDB_INVALID_ADDRESS && file_address != LLDB_INVALID_ADDRESS)
+ {
+ s->Printf ("Kernel slid 0x%" PRIx64 " in memory.\n", m_load_address - file_address);
+ }
+ }
+ {
+ s->Printf ("Loaded kernel file %s\n",
+ m_module_sp->GetFileSpec().GetPath().c_str());
+ }
+ s->Flush ();
+ }
}
return is_loaded;
}
+uint32_t
+DynamicLoaderDarwinKernel::KextImageInfo::GetAddressByteSize ()
+{
+ if (m_memory_module_sp)
+ return m_memory_module_sp->GetArchitecture().GetAddressByteSize();
+ if (m_module_sp)
+ return m_module_sp->GetArchitecture().GetAddressByteSize();
+ return 0;
+}
+
+lldb::ByteOrder
+DynamicLoaderDarwinKernel::KextImageInfo::GetByteOrder()
+{
+ if (m_memory_module_sp)
+ return m_memory_module_sp->GetArchitecture().GetByteOrder();
+ if (m_module_sp)
+ return m_module_sp->GetArchitecture().GetByteOrder();
+ return lldb::endian::InlHostByteOrder();
+}
+
+lldb_private::ArchSpec
+DynamicLoaderDarwinKernel::KextImageInfo::GetArchitecture () const
+{
+ if (m_memory_module_sp)
+ return m_memory_module_sp->GetArchitecture();
+ if (m_module_sp)
+ return m_module_sp->GetArchitecture();
+ return lldb_private::ArchSpec ();
+}
+
+
//----------------------------------------------------------------------
// Load the kernel module and initialize the "m_kernel" member. Return
// true _only_ if the kernel is loaded the first time through (subsequent
@@ -313,24 +1009,52 @@ DynamicLoaderDarwinKernel::LoadKernelMod
{
if (!m_kext_summary_header_ptr_addr.IsValid())
{
- m_kernel.Clear(false);
- m_kernel.module_sp = m_process->GetTarget().GetExecutableModule();
- strncpy(m_kernel.name, "mach_kernel", sizeof(m_kernel.name));
- if (m_kernel.address == LLDB_INVALID_ADDRESS)
+ m_kernel.Clear();
+ m_kernel.SetModule (m_process->GetTarget().GetExecutableModule());
+ m_kernel.SetIsKernel(true);
+
+ ConstString kernel_name("mach_kernel");
+ if (m_kernel.GetModule().get()
+ && m_kernel.GetModule()->GetObjectFile()
+ && !m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename().IsEmpty())
+ {
+ kernel_name = m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename();
+ }
+ m_kernel.SetName (kernel_name.AsCString());
+
+ if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS)
{
- m_kernel.address = m_process->GetImageInfoAddress ();
- if (m_kernel.address == LLDB_INVALID_ADDRESS && m_kernel.module_sp)
+ m_kernel.SetLoadAddress(m_kernel_load_address);
+ if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS && m_kernel.GetModule())
{
// We didn't get a hint from the process, so we will
// try the kernel at the address that it exists at in
// the file if we have one
- ObjectFile *kernel_object_file = m_kernel.module_sp->GetObjectFile();
+ ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile();
if (kernel_object_file)
- m_kernel.address = kernel_object_file->GetHeaderAddress().GetFileAddress();
+ {
+ addr_t load_address = kernel_object_file->GetHeaderAddress().GetLoadAddress(&m_process->GetTarget());
+ addr_t file_address = kernel_object_file->GetHeaderAddress().GetFileAddress();
+ if (load_address != LLDB_INVALID_ADDRESS && load_address != 0)
+ {
+ m_kernel.SetLoadAddress (load_address);
+ if (load_address != file_address)
+ {
+ // Don't accidentally relocate the kernel to the File address --
+ // the Load address has already been set to its actual in-memory address.
+ // Mark it as IsLoaded.
+ m_kernel.SetProcessStopId (m_process->GetStopID());
+ }
+ }
+ else
+ {
+ m_kernel.SetLoadAddress(file_address);
+ }
+ }
}
}
- if (m_kernel.address != LLDB_INVALID_ADDRESS)
+ if (m_kernel.GetLoadAddress() != LLDB_INVALID_ADDRESS)
{
if (!m_kernel.LoadImageUsingMemoryModule (m_process))
{
@@ -338,10 +1062,10 @@ DynamicLoaderDarwinKernel::LoadKernelMod
}
}
- if (m_kernel.IsLoaded())
+ if (m_kernel.IsLoaded() && m_kernel.GetModule())
{
static ConstString kext_summary_symbol ("gLoadedKextSummaries");
- const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
+ const Symbol *symbol = m_kernel.GetModule()->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData);
if (symbol)
{
m_kext_summary_header_ptr_addr = symbol->GetAddress();
@@ -351,7 +1075,7 @@ DynamicLoaderDarwinKernel::LoadKernelMod
}
else
{
- m_kernel.Clear(false);
+ m_kernel.Clear();
}
}
}
@@ -376,14 +1100,14 @@ DynamicLoaderDarwinKernel::BreakpointHit
user_id_t break_id,
user_id_t break_loc_id)
{
- LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf ("DynamicLoaderDarwinKernel::BreakpointHit (...)\n");
ReadAllKextSummaries ();
if (log)
- PutToLog(log.get());
+ PutToLog(log);
return GetStopWhenImagesChange();
}
@@ -396,7 +1120,6 @@ DynamicLoaderDarwinKernel::ReadKextSumma
// the all image infos is already valid for this process stop ID
- m_kext_summaries.clear();
if (m_kext_summary_header_ptr_addr.IsValid())
{
const uint32_t addr_size = m_kernel.GetAddressByteSize ();
@@ -420,7 +1143,7 @@ DynamicLoaderDarwinKernel::ReadKextSumma
const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error);
if (bytes_read == count)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
m_kext_summary_header.version = data.GetU32(&offset);
if (m_kext_summary_header.version >= 2)
{
@@ -441,96 +1164,194 @@ DynamicLoaderDarwinKernel::ReadKextSumma
return false;
}
+// We've either (a) just attached to a new kernel, or (b) the kexts-changed breakpoint was hit
+// and we need to figure out what kexts have been added or removed.
+// Read the kext summaries from the inferior kernel memory, compare them against the
+// m_known_kexts vector and update the m_known_kexts vector as needed to keep in sync with the
+// inferior.
bool
-DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr,
- uint32_t count)
+DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr, uint32_t count)
{
- OSKextLoadedKextSummary::collection kext_summaries;
- LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ KextImageInfo::collection kext_summaries;
+ Log *log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
- log->Printf ("Adding %d modules.\n", count);
+ log->Printf ("Kexts-changed breakpoint hit, there are %d kexts currently.\n", count);
Mutex::Locker locker(m_mutex);
if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries))
return false;
- Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
- for (uint32_t i = 0; i < count; i++)
+ // read the plugin.dynamic-loader.darwin-kernel.load-kexts setting -- if the user requested no
+ // kext loading, don't print any messages about kexts & don't try to read them.
+ const bool load_kexts = GetGlobalProperties()->GetLoadKexts();
+
+ // By default, all kexts we've loaded in the past are marked as "remove" and all of the kexts
+ // we just found out about from ReadKextSummaries are marked as "add".
+ std::vector<bool> to_be_removed(m_known_kexts.size(), true);
+ std::vector<bool> to_be_added(count, true);
+
+ int number_of_new_kexts_being_added = 0;
+ int number_of_old_kexts_being_removed = m_known_kexts.size();
+
+ const uint32_t new_kexts_size = kext_summaries.size();
+ const uint32_t old_kexts_size = m_known_kexts.size();
+
+ // The m_known_kexts vector may have entries that have been Cleared,
+ // or are a kernel.
+ for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++)
{
- if (s)
+ bool ignore = false;
+ KextImageInfo &image_info = m_known_kexts[old_kext];
+ if (image_info.IsKernel())
{
- const uint8_t *u = (const uint8_t *)kext_summaries[i].uuid.GetBytes();
- if (u)
- {
- s->Printf("Loading kext: %2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X 0x%16.16llx \"%s\"...",
- u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
- u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
- kext_summaries[i].address, kext_summaries[i].name);
- }
- else
- {
- s->Printf("0x%16.16llx \"%s\"...", kext_summaries[i].address, kext_summaries[i].name);
- }
+ ignore = true;
+ }
+ else if (image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS && !image_info.GetModule())
+ {
+ ignore = true;
}
-
- if (!kext_summaries[i].LoadImageUsingMemoryModule (m_process))
- kext_summaries[i].LoadImageAtFileAddress (m_process);
- if (s)
+ if (ignore)
+ {
+ number_of_old_kexts_being_removed--;
+ to_be_removed[old_kext] = false;
+ }
+ }
+
+ // Scan over the list of kexts we just read from the kernel, note those that
+ // need to be added and those already loaded.
+ for (uint32_t new_kext = 0; new_kext < new_kexts_size; new_kext++)
+ {
+ bool add_this_one = true;
+ for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++)
{
- if (kext_summaries[i].module_sp)
+ if (m_known_kexts[old_kext] == kext_summaries[new_kext])
{
- if (kext_summaries[i].module_sp->GetFileSpec().GetDirectory())
- s->Printf("\n found kext: %s/%s\n",
- kext_summaries[i].module_sp->GetFileSpec().GetDirectory().AsCString(),
- kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
- else
- s->Printf("\n found kext: %s\n",
- kext_summaries[i].module_sp->GetFileSpec().GetFilename().AsCString());
+ // We already have this kext, don't re-load it.
+ to_be_added[new_kext] = false;
+ // This kext is still present, do not remove it.
+ to_be_removed[old_kext] = false;
+
+ number_of_old_kexts_being_removed--;
+ add_this_one = false;
+ break;
}
- else
- s->Printf (" failed to locate/load.\n");
}
-
- if (log)
- kext_summaries[i].PutToLog (log.get());
+ if (add_this_one)
+ {
+ number_of_new_kexts_being_added++;
+ }
}
- bool return_value = AddModulesUsingImageInfos (kext_summaries);
- return return_value;
-}
-// Adds the modules in image_infos to m_kext_summaries.
-// NB don't call this passing in m_kext_summaries.
+ if (number_of_new_kexts_being_added == 0 && number_of_old_kexts_being_removed == 0)
+ return true;
-bool
-DynamicLoaderDarwinKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos)
-{
- // Now add these images to the main list.
- ModuleList loaded_module_list;
-
- for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
+ Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
+ if (s && load_kexts)
{
- OSKextLoadedKextSummary &image_info = image_infos[idx];
- m_kext_summaries.push_back(image_info);
-
- if (image_info.module_sp && m_process->GetStopID() == image_info.load_process_stop_id)
- loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp);
+ if (number_of_new_kexts_being_added > 0 && number_of_old_kexts_being_removed > 0)
+ {
+ s->Printf ("Loading %d kext modules and unloading %d kext modules ", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
+ }
+ else if (number_of_new_kexts_being_added > 0)
+ {
+ s->Printf ("Loading %d kext modules ", number_of_new_kexts_being_added);
+ }
+ else if (number_of_old_kexts_being_removed > 0)
+ {
+ s->Printf ("Unloading %d kext modules ", number_of_old_kexts_being_removed);
+ }
}
-
- if (loaded_module_list.GetSize() > 0)
+
+ if (log)
+ {
+ if (load_kexts)
+ {
+ log->Printf ("DynamicLoaderDarwinKernel::ParseKextSummaries: %d kexts added, %d kexts removed", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
+ }
+ else
+ {
+ log->Printf ("DynamicLoaderDarwinKernel::ParseKextSummaries kext loading is disabled, else would have %d kexts added, %d kexts removed", number_of_new_kexts_being_added, number_of_old_kexts_being_removed);
+ }
+ }
+
+
+ if (number_of_new_kexts_being_added > 0)
{
+ ModuleList loaded_module_list;
+
+ const uint32_t num_of_new_kexts = kext_summaries.size();
+ for (uint32_t new_kext = 0; new_kext < num_of_new_kexts; new_kext++)
+ {
+ if (to_be_added[new_kext] == true)
+ {
+ KextImageInfo &image_info = kext_summaries[new_kext];
+ if (load_kexts)
+ {
+ if (!image_info.LoadImageUsingMemoryModule (m_process))
+ {
+ image_info.LoadImageAtFileAddress (m_process);
+ }
+ }
+
+ m_known_kexts.push_back(image_info);
+
+ if (image_info.GetModule() && m_process->GetStopID() == image_info.GetProcessStopId())
+ loaded_module_list.AppendIfNeeded (image_info.GetModule());
+
+ if (s && load_kexts)
+ s->Printf (".");
+
+ if (log)
+ kext_summaries[new_kext].PutToLog (log);
+ }
+ }
m_process->GetTarget().ModulesDidLoad (loaded_module_list);
}
+
+ if (number_of_old_kexts_being_removed > 0)
+ {
+ ModuleList loaded_module_list;
+ const uint32_t num_of_old_kexts = m_known_kexts.size();
+ for (uint32_t old_kext = 0; old_kext < num_of_old_kexts; old_kext++)
+ {
+ ModuleList unloaded_module_list;
+ if (to_be_removed[old_kext])
+ {
+ KextImageInfo &image_info = m_known_kexts[old_kext];
+ // You can't unload the kernel.
+ if (!image_info.IsKernel())
+ {
+ if (image_info.GetModule())
+ {
+ unloaded_module_list.AppendIfNeeded (image_info.GetModule());
+ }
+ if (s)
+ s->Printf (".");
+ image_info.Clear();
+ // should pull it out of the KextImageInfos vector but that would mutate the list and invalidate
+ // the to_be_removed bool vector; leaving it in place once Cleared() is relatively harmless.
+ }
+ }
+ m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
+ }
+ }
+
+ if (s && load_kexts)
+ {
+ s->Printf (" done.\n");
+ s->Flush ();
+ }
+
return true;
}
-
uint32_t
DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr,
uint32_t image_infos_count,
- OSKextLoadedKextSummary::collection &image_infos)
+ KextImageInfo::collection &image_infos)
{
const ByteOrder endian = m_kernel.GetByteOrder();
const uint32_t addr_size = m_kernel.GetAddressByteSize();
@@ -540,10 +1361,6 @@ DynamicLoaderDarwinKernel::ReadKextSumma
DataBufferHeap data(count, 0);
Error error;
- Stream *s = &m_process->GetTarget().GetDebugger().GetOutputStream();
-
- if (s)
- s->Printf ("Reading %u kext summaries...\n", image_infos_count);
const bool prefer_file_cache = false;
const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr,
prefer_file_cache,
@@ -559,35 +1376,15 @@ DynamicLoaderDarwinKernel::ReadKextSumma
i < image_infos.size() && extractor.ValidOffsetForDataOfSize(kext_summary_offset, m_kext_summary_header.entry_size);
++i, kext_summary_offset += m_kext_summary_header.entry_size)
{
- uint32_t offset = kext_summary_offset;
+ lldb::offset_t offset = kext_summary_offset;
const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME);
if (name_data == NULL)
break;
- memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME);
- image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16));
- image_infos[i].address = extractor.GetU64(&offset);
- if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget()))
- m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address);
- image_infos[i].size = extractor.GetU64(&offset);
- image_infos[i].version = extractor.GetU64(&offset);
- image_infos[i].load_tag = extractor.GetU32(&offset);
- image_infos[i].flags = extractor.GetU32(&offset);
- if ((offset - kext_summary_offset) < m_kext_summary_header.entry_size)
- {
- image_infos[i].reference_list = extractor.GetU64(&offset);
- }
- else
- {
- image_infos[i].reference_list = 0;
- }
-// printf ("[%3u] %*.*s: address=0x%16.16llx, size=0x%16.16llx, version=0x%16.16llx, load_tag=0x%8.8x, flags=0x%8.8x\n",
-// i,
-// KERNEL_MODULE_MAX_NAME, KERNEL_MODULE_MAX_NAME, (char *)name_data,
-// image_infos[i].address,
-// image_infos[i].size,
-// image_infos[i].version,
-// image_infos[i].load_tag,
-// image_infos[i].flags);
+ image_infos[i].SetName ((const char *) name_data);
+ UUID uuid (extractor.GetData (&offset, 16), 16);
+ image_infos[i].SetUUID (uuid);
+ image_infos[i].SetLoadAddress (extractor.GetU64(&offset));
+ image_infos[i].SetSize (extractor.GetU64(&offset));
}
if (i < image_infos.size())
image_infos.resize(i);
@@ -602,8 +1399,6 @@ DynamicLoaderDarwinKernel::ReadKextSumma
bool
DynamicLoaderDarwinKernel::ReadAllKextSummaries ()
{
- LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
-
Mutex::Locker locker(m_mutex);
if (ReadKextSummaryHeader ())
@@ -614,7 +1409,7 @@ DynamicLoaderDarwinKernel::ReadAllKextSu
summary_addr.Slide(m_kext_summary_header.GetSize());
if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count))
{
- m_kext_summaries.clear();
+ m_known_kexts.clear();
}
return true;
}
@@ -626,13 +1421,13 @@ DynamicLoaderDarwinKernel::ReadAllKextSu
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
void
-DynamicLoaderDarwinKernel::OSKextLoadedKextSummary::PutToLog (Log *log) const
+DynamicLoaderDarwinKernel::KextImageInfo::PutToLog (Log *log) const
{
if (log == NULL)
return;
- const uint8_t *u = (uint8_t *)uuid.GetBytes();
+ const uint8_t *u = (uint8_t *) m_uuid.GetBytes();
- if (address == LLDB_INVALID_ADDRESS)
+ if (m_load_address == LLDB_INVALID_ADDRESS)
{
if (u)
{
@@ -641,26 +1436,25 @@ DynamicLoaderDarwinKernel::OSKextLoadedK
u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11],
u[12], u[13], u[14], u[15],
- name);
+ m_name.c_str());
}
else
- log->Printf("\tname=\"%s\" (UNLOADED)", name);
+ log->Printf("\tname=\"%s\" (UNLOADED)", m_name.c_str());
}
else
{
if (u)
{
- log->Printf("\taddr=0x%16.16llx size=0x%16.16llx version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
- address, size, version, load_tag, flags, reference_list,
+ log->Printf("\taddr=0x%16.16" PRIx64 " size=0x%16.16" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
+ m_load_address, m_size,
u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11], u[12], u[13], u[14], u[15],
- name);
+ m_name.c_str());
}
else
{
- log->Printf("\t[0x%16.16llx - 0x%16.16llx) version=0x%16.16llx load-tag=0x%8.8x flags=0x%8.8x ref-list=0x%16.16llx name=\"%s\"",
- address, address+size, version, load_tag, flags, reference_list,
- name);
+ log->Printf("\t[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") name=\"%s\"",
+ m_load_address, m_load_address+m_size, m_name.c_str());
}
}
}
@@ -676,19 +1470,19 @@ DynamicLoaderDarwinKernel::PutToLog(Log
return;
Mutex::Locker locker(m_mutex);
- log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u }",
+ log->Printf("gLoadedKextSummaries = 0x%16.16" PRIx64 " { version=%u, entry_size=%u, entry_count=%u }",
m_kext_summary_header_addr.GetFileAddress(),
m_kext_summary_header.version,
m_kext_summary_header.entry_size,
m_kext_summary_header.entry_count);
size_t i;
- const size_t count = m_kext_summaries.size();
+ const size_t count = m_known_kexts.size();
if (count > 0)
{
log->PutCString("Loaded:");
for (i = 0; i<count; i++)
- m_kext_summaries[i].PutToLog(log);
+ m_known_kexts[i].PutToLog(log);
}
}
@@ -698,13 +1492,12 @@ DynamicLoaderDarwinKernel::PrivateInitia
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
Clear(true);
m_process = process;
- m_process->GetTarget().GetSectionLoadList().Clear();
}
void
DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded ()
{
- if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.module_sp)
+ if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.GetModule())
{
DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState()));
@@ -712,7 +1505,7 @@ DynamicLoaderDarwinKernel::SetNotificati
const bool internal_bp = true;
const LazyBool skip_prologue = eLazyBoolNo;
FileSpecList module_spec_list;
- module_spec_list.Append (m_kernel.module_sp->GetFileSpec());
+ module_spec_list.Append (m_kernel.GetModule()->GetFileSpec());
Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list,
NULL,
"OSKextLoadedKextSummariesUpdated",
@@ -753,9 +1546,6 @@ DynamicLoaderDarwinKernel::PrivateProces
case eStateCrashed:
case eStateSuspended:
break;
-
- default:
- break;
}
}
@@ -763,7 +1553,7 @@ ThreadPlanSP
DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
{
ThreadPlanSP thread_plan_sp;
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
log->Printf ("Could not find symbol for step through.");
return thread_plan_sp;
@@ -782,7 +1572,8 @@ DynamicLoaderDarwinKernel::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ DebuggerInitialize);
}
void
@@ -791,11 +1582,24 @@ DynamicLoaderDarwinKernel::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+void
+DynamicLoaderDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForDynamicLoaderPlugin (debugger, DynamicLoaderDarwinKernelProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForDynamicLoaderPlugin (debugger,
+ GetGlobalProperties()->GetValueProperties(),
+ ConstString ("Properties for the DynamicLoaderDarwinKernel plug-in."),
+ is_global_setting);
+ }
+}
-const char *
+lldb_private::ConstString
DynamicLoaderDarwinKernel::GetPluginNameStatic()
{
- return "dynamic-loader.macosx-kernel";
+ static ConstString g_name("darwin-kernel");
+ return g_name;
}
const char *
@@ -808,15 +1612,9 @@ DynamicLoaderDarwinKernel::GetPluginDesc
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
DynamicLoaderDarwinKernel::GetPluginName()
{
- return "DynamicLoaderDarwinKernel";
-}
-
-const char *
-DynamicLoaderDarwinKernel::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -826,3 +1624,25 @@ DynamicLoaderDarwinKernel::GetPluginVers
return 1;
}
+lldb::ByteOrder
+DynamicLoaderDarwinKernel::GetByteOrderFromMagic (uint32_t magic)
+{
+ switch (magic)
+ {
+ case llvm::MachO::HeaderMagic32:
+ case llvm::MachO::HeaderMagic64:
+ return lldb::endian::InlHostByteOrder();
+
+ case llvm::MachO::HeaderMagic32Swapped:
+ case llvm::MachO::HeaderMagic64Swapped:
+ if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
+ return lldb::eByteOrderLittle;
+ else
+ return lldb::eByteOrderBig;
+
+ default:
+ break;
+ }
+ return lldb::eByteOrderInvalid;
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h Thu Jun 6 19:06:43 2013
@@ -38,7 +38,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -47,10 +47,14 @@ public:
static lldb_private::DynamicLoader *
CreateInstance (lldb_private::Process *process, bool force);
- DynamicLoaderDarwinKernel (lldb_private::Process *process);
+ static void
+ DebuggerInitialize (lldb_private::Debugger &debugger);
+
+ DynamicLoaderDarwinKernel (lldb_private::Process *process, lldb::addr_t kernel_addr);
virtual
~DynamicLoaderDarwinKernel ();
+
//------------------------------------------------------------------
/// Called after attaching a process.
///
@@ -73,12 +77,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -89,7 +90,7 @@ protected:
void
PrivateProcessStateChanged (lldb_private::Process *process,
lldb::StateType state);
-
+
void
UpdateIfNeeded();
@@ -109,8 +110,8 @@ protected:
lldb::user_id_t break_loc_id);
bool
- BreakpointHit (lldb_private::StoppointCallbackContext *context,
- lldb::user_id_t break_id,
+ BreakpointHit (lldb_private::StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
uint32_t
GetAddrByteSize()
@@ -119,26 +120,8 @@ protected:
}
static lldb::ByteOrder
- GetByteOrderFromMagic (uint32_t magic)
- {
- switch (magic)
- {
- case llvm::MachO::HeaderMagic32:
- case llvm::MachO::HeaderMagic64:
- return lldb::endian::InlHostByteOrder();
-
- case llvm::MachO::HeaderMagic32Swapped:
- case llvm::MachO::HeaderMagic64Swapped:
- if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
- return lldb::eByteOrderLittle;
- else
- return lldb::eByteOrderBig;
+ GetByteOrderFromMagic (uint32_t magic);
- default:
- break;
- }
- return lldb::eByteOrderInvalid;
- }
enum
{
KERNEL_MODULE_MAX_NAME = 64u,
@@ -148,58 +131,51 @@ protected:
// 4 byte flags
KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u
};
-
- struct OSKextLoadedKextSummary
+
+ // class KextImageInfo represents a single kext or kernel binary image.
+ // The class was designed to hold the information from the OSKextLoadedKextSummary
+ // structure (in libkern/libkern/OSKextLibPrivate.h from xnu). The kernel maintains
+ // a list of loded kexts in memory (the OSKextLoadedKextSummaryHeader structure,
+ // which points to an array of OSKextLoadedKextSummary's).
+ //
+ // A KextImageInfos may have -
+ //
+ // 1. The load address, name, UUID, and size of a kext/kernel binary in memory
+ // (read straight out of the kernel's list-of-kexts loaded)
+ // 2. A ModuleSP based on a MemoryModule read out of the kernel's memory
+ // (very unlikely to have any symbolic information)
+ // 3. A ModuleSP for an on-disk copy of the kext binary, possibly with debug info
+ // or a dSYM
+ //
+ // For performance reasons, the developer may prefer that lldb not load the kexts out
+ // of memory at the start of a kernel session. But we should build up / maintain a
+ // list of kexts that the kernel has told us about so we can relocate a kext module
+ // later if the user explicitly adds it to the target.
+
+ class KextImageInfo
{
- char name[KERNEL_MODULE_MAX_NAME];
- lldb::ModuleSP module_sp;
- uint32_t load_process_stop_id;
- lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
- lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files
- uint64_t address;
- uint64_t size;
- uint64_t version;
- uint32_t load_tag;
- uint32_t flags;
- uint64_t reference_list;
-
- OSKextLoadedKextSummary() :
- module_sp (),
- load_process_stop_id (UINT32_MAX),
- uuid (),
- so_address (),
- address (LLDB_INVALID_ADDRESS),
- size (0),
- version (0),
- load_tag (0),
- flags (0),
- reference_list (0)
- {
- name[0] = '\0';
- }
-
- bool
- IsLoaded ()
- {
- return load_process_stop_id != UINT32_MAX;
- }
+ public:
+ KextImageInfo () :
+ m_name (),
+ m_module_sp (),
+ m_memory_module_sp (),
+ m_load_process_stop_id (UINT32_MAX),
+ m_uuid (),
+ m_load_address (LLDB_INVALID_ADDRESS),
+ m_size (0),
+ m_kernel_image (false)
+ { }
void
- Clear (bool load_cmd_data_only)
+ Clear ()
{
- if (!load_cmd_data_only)
- {
- so_address.Clear();
- address = LLDB_INVALID_ADDRESS;
- size = 0;
- version = 0;
- load_tag = 0;
- flags = 0;
- reference_list = 0;
- name[0] = '\0';
- }
- module_sp.reset();
- load_process_stop_id = UINT32_MAX;
+ m_load_address = LLDB_INVALID_ADDRESS;
+ m_size = 0;
+ m_name.clear ();
+ m_uuid.Clear();
+ m_module_sp.reset();
+ m_memory_module_sp.reset();
+ m_load_process_stop_id = UINT32_MAX;
}
bool
@@ -207,57 +183,88 @@ protected:
bool
LoadImageUsingMemoryModule (lldb_private::Process *process);
-
-// bool
-// operator == (const OSKextLoadedKextSummary& rhs) const
-// {
-// return address == rhs.address
-// && size == rhs.size
-// //&& module_sp.get() == rhs.module_sp.get()
-// && uuid == rhs.uuid
-// && version == rhs.version
-// && load_tag == rhs.load_tag
-// && flags == rhs.flags
-// && reference_list == rhs.reference_list
-// && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0;
-// }
-//
+
bool
- UUIDValid() const
+ IsLoaded ()
{
- return uuid.IsValid();
+ return m_load_process_stop_id != UINT32_MAX;
}
+ void
+ SetLoadAddress (lldb::addr_t load_addr); // Address of the Mach-O header for this binary
+
+ lldb::addr_t
+ GetLoadAddress () const; // Address of the Mach-O header for this binary
+
+ lldb_private::UUID
+ GetUUID () const;
+
+ void
+ SetUUID (const lldb_private::UUID &uuid);
+
+ void
+ SetName (const char *);
+
+ std::string
+ GetName () const;
+
+ void
+ SetModule (lldb::ModuleSP module);
+
+ lldb::ModuleSP
+ GetModule ();
+
+ // try to fill in m_memory_module_sp from memory based on the m_load_address
+ bool
+ ReadMemoryModule (lldb_private::Process *process);
+
+ bool
+ IsKernel () const; // true if this is the mach_kernel; false if this is a kext
+
+ void
+ SetIsKernel (bool is_kernel);
+
+ uint64_t
+ GetSize () const;
+
+ void
+ SetSize (uint64_t size);
+
uint32_t
- GetAddressByteSize ()
- {
- if (module_sp)
- return module_sp->GetArchitecture().GetAddressByteSize();
- return 0;
- }
+ GetProcessStopId () const; // the stop-id when this binary was first noticed
+
+ void
+ SetProcessStopId (uint32_t stop_id);
+
+ bool
+ operator== (const KextImageInfo &rhs);
+
+ uint32_t
+ GetAddressByteSize (); // as determined by Mach-O header
lldb::ByteOrder
- GetByteOrder()
- {
- if (module_sp)
- return module_sp->GetArchitecture().GetByteOrder();
- return lldb::endian::InlHostByteOrder();
- }
+ GetByteOrder(); // as determined by Mach-O header
lldb_private::ArchSpec
- GetArchitecture () const
- {
- if (module_sp)
- return module_sp->GetArchitecture();
- return lldb_private::ArchSpec ();
- }
+ GetArchitecture () const; // as determined by Mach-O header
void
PutToLog (lldb_private::Log *log) const;
- typedef std::vector<OSKextLoadedKextSummary> collection;
+ typedef std::vector<KextImageInfo> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
+
+ private:
+ std::string m_name;
+ lldb::ModuleSP m_module_sp;
+ lldb::ModuleSP m_memory_module_sp;
+ uint32_t m_load_process_stop_id; // the stop-id when this module was added to the Target
+ lldb_private::UUID m_uuid; // UUID for this dylib if it has one, else all zeros
+ lldb::addr_t m_load_address;
+ uint64_t m_size;
+ bool m_kernel_image; // true if this is the kernel, false if this is a kext
+
};
struct OSKextLoadedKextSummaryHeader
@@ -285,7 +292,7 @@ protected:
default: break;
}
// Version 2 and above has version, entry_size, entry_count, and reserved
- return 16;
+ return 16;
}
void
@@ -318,31 +325,48 @@ protected:
bool
ReadKextSummaryHeader ();
-
+
bool
- ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
+ ParseKextSummaries (const lldb_private::Address &kext_summary_addr,
uint32_t count);
-
- bool
- AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos);
-
+
void
- UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos,
- uint32_t infos_count,
+ UpdateImageInfosHeaderAndLoadCommands(KextImageInfo::collection &image_infos,
+ uint32_t infos_count,
bool update_executable);
uint32_t
ReadKextSummaries (const lldb_private::Address &kext_summary_addr,
- uint32_t image_infos_count,
- OSKextLoadedKextSummary::collection &image_infos);
+ uint32_t image_infos_count,
+ KextImageInfo::collection &image_infos);
+
+ static lldb::addr_t
+ SearchForDarwinKernel (lldb_private::Process *process);
- OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used
- lldb_private::Address m_kext_summary_header_ptr_addr;
- lldb_private::Address m_kext_summary_header_addr;
- OSKextLoadedKextSummaryHeader m_kext_summary_header;
- OSKextLoadedKextSummary::collection m_kext_summaries;
- mutable lldb_private::Mutex m_mutex;
- lldb::user_id_t m_break_id;
+ static lldb::addr_t
+ SearchForKernelAtSameLoadAddr (lldb_private::Process *process);
+
+ static lldb::addr_t
+ SearchForKernelWithDebugHints (lldb_private::Process *process);
+
+ static lldb::addr_t
+ SearchForKernelNearPC (lldb_private::Process *process);
+
+ static lldb::addr_t
+ SearchForKernelViaExhaustiveSearch (lldb_private::Process *process);
+
+ static lldb_private::UUID
+ CheckForKernelImageAtAddress (lldb::addr_t addr, lldb_private::Process *process);
+
+ lldb::addr_t m_kernel_load_address;
+ KextImageInfo m_kernel; // Info about the current kernel image being used
+
+ lldb_private::Address m_kext_summary_header_ptr_addr;
+ lldb_private::Address m_kext_summary_header_addr;
+ OSKextLoadedKextSummaryHeader m_kext_summary_header;
+ KextImageInfo::collection m_known_kexts;
+ mutable lldb_private::Mutex m_mutex;
+ lldb::user_id_t m_break_id;
private:
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwinKernel);
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Thu Jun 6 19:06:43 2013
@@ -15,8 +15,11 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/RegisterContext.h"
@@ -35,6 +38,10 @@
#define DEBUG_PRINTF(fmt, ...)
#endif
+#ifndef __APPLE__
+#include "Utility/UuidCompatibility.h"
+#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -136,7 +143,8 @@ DynamicLoaderMacOSXDYLD::DynamicLoaderMa
m_break_id(LLDB_INVALID_BREAK_ID),
m_dyld_image_infos(),
m_dyld_image_infos_stop_id (UINT32_MAX),
- m_mutex(Mutex::eMutexTypeRecursive)
+ m_mutex(Mutex::eMutexTypeRecursive),
+ m_process_image_addr_is_all_images_infos (false)
{
}
@@ -176,6 +184,54 @@ DynamicLoaderMacOSXDYLD::DidLaunch ()
SetNotificationBreakpoint ();
}
+bool
+DynamicLoaderMacOSXDYLD::ProcessDidExec ()
+{
+ if (m_process)
+ {
+ // If we are stopped after an exec, we will have only one thread...
+ if (m_process->GetThreadList().GetSize() == 1)
+ {
+ // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr"
+ // value differs from the Process' image info address. When a process
+ // execs itself it might cause a change if ASLR is enabled.
+ const addr_t shlib_addr = m_process->GetImageInfoAddress ();
+ if (m_process_image_addr_is_all_images_infos == true && shlib_addr != m_dyld_all_image_infos_addr)
+ {
+ // The image info address from the process is the 'dyld_all_image_infos'
+ // address and it has changed.
+ return true;
+ }
+
+ if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address)
+ {
+ // The image info address from the process is the mach_header
+ // address for dyld and it has changed.
+ return true;
+ }
+
+ // ASLR might be disabled and dyld could have ended up in the same
+ // location. We should try and detect if we are stopped at '_dyld_start'
+ ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0));
+ if (thread_sp)
+ {
+ lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0));
+ if (frame_sp)
+ {
+ const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+ if (symbol)
+ {
+ if (symbol->GetName() == ConstString("_dyld_start"))
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
//----------------------------------------------------------------------
// Clear out the state of this class.
@@ -186,7 +242,7 @@ DynamicLoaderMacOSXDYLD::Clear (bool cle
Mutex::Locker locker(m_mutex);
if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id))
- m_process->ClearBreakpointSiteByID(m_break_id);
+ m_process->GetTarget().RemoveBreakpointByID (m_break_id);
if (clear_process)
m_process = NULL;
@@ -221,29 +277,33 @@ DynamicLoaderMacOSXDYLD::LocateDYLD()
// mach header for dyld, or it might point to the
// dyld_all_image_infos struct
const addr_t shlib_addr = m_process->GetImageInfoAddress ();
-
- ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
- uint8_t buf[4];
- DataExtractor data (buf, sizeof(buf), byte_order, 4);
- Error error;
- if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4)
+ if (shlib_addr != LLDB_INVALID_ADDRESS)
{
- uint32_t offset = 0;
- uint32_t magic = data.GetU32 (&offset);
- switch (magic)
- {
- case llvm::MachO::HeaderMagic32:
- case llvm::MachO::HeaderMagic64:
- case llvm::MachO::HeaderMagic32Swapped:
- case llvm::MachO::HeaderMagic64Swapped:
- return ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
-
- default:
- break;
+ ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
+ uint8_t buf[4];
+ DataExtractor data (buf, sizeof(buf), byte_order, 4);
+ Error error;
+ if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4)
+ {
+ lldb::offset_t offset = 0;
+ uint32_t magic = data.GetU32 (&offset);
+ switch (magic)
+ {
+ case llvm::MachO::HeaderMagic32:
+ case llvm::MachO::HeaderMagic64:
+ case llvm::MachO::HeaderMagic32Swapped:
+ case llvm::MachO::HeaderMagic64Swapped:
+ m_process_image_addr_is_all_images_infos = false;
+ return ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
+
+ default:
+ break;
+ }
}
+ // Maybe it points to the all image infos?
+ m_dyld_all_image_infos_addr = shlib_addr;
+ m_process_image_addr_is_all_images_infos = true;
}
- // Maybe it points to the all image infos?
- m_dyld_all_image_infos_addr = shlib_addr;
}
if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
@@ -280,11 +340,13 @@ DynamicLoaderMacOSXDYLD::LocateDYLD()
}
ModuleSP
-DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
+DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr)
{
if (did_create_ptr)
*did_create_ptr = false;
- ModuleList &target_images = m_process->GetTarget().GetImages();
+
+ Target &target = m_process->GetTarget();
+ const ModuleList &target_images = target.GetImages();
ModuleSpec module_spec (image_info.file_spec, image_info.GetArchitecture ());
module_spec.GetUUID() = image_info.uuid;
ModuleSP module_sp (target_images.FindFirstModule (module_spec));
@@ -301,16 +363,9 @@ DynamicLoaderMacOSXDYLD::FindTargetModul
{
if (can_create)
{
- module_sp = m_process->GetTarget().GetSharedModule (module_spec);
+ module_sp = target.GetSharedModule (module_spec);
if (!module_sp || module_sp->GetObjectFile() == NULL)
- {
- const bool add_image_to_target = true;
- const bool load_image_sections_in_target = false;
- module_sp = m_process->ReadModuleFromMemory (image_info.file_spec,
- image_info.address,
- add_image_to_target,
- load_image_sections_in_target);
- }
+ module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address);
if (did_create_ptr)
*did_create_ptr = (bool) module_sp;
@@ -344,12 +399,14 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFro
}
}
+ Target &target = m_process->GetTarget();
+
if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && dyld_module_sp.get())
{
static ConstString g_dyld_all_image_infos ("dyld_all_image_infos");
const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType (g_dyld_all_image_infos, eSymbolTypeData);
if (symbol)
- m_dyld_all_image_infos_addr = symbol->GetAddress().GetLoadAddress(&m_process->GetTarget());
+ m_dyld_all_image_infos_addr = symbol->GetAddress().GetLoadAddress(&target);
}
// Update all image infos
@@ -360,9 +417,15 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFro
// it again (since Target::SetExecutableModule() will clear the
// images). So append the dyld module back to the list if it is
/// unique!
- if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
- UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
+ if (dyld_module_sp)
+ {
+ target.GetImages().AppendIfNeeded (dyld_module_sp);
+ // At this point we should have read in dyld's module, and so we should set breakpoints in it:
+ ModuleList modules;
+ modules.Append(dyld_module_sp);
+ target.ModulesDidLoad(modules);
+ }
return true;
}
}
@@ -375,40 +438,6 @@ DynamicLoaderMacOSXDYLD::NeedToLocateDYL
return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS;
}
-bool
-DynamicLoaderMacOSXDYLD::UpdateCommPageLoadAddress(Module *module)
-{
- bool changed = false;
- if (module)
- {
- ObjectFile *image_object_file = module->GetObjectFile();
- if (image_object_file)
- {
- SectionList *section_list = image_object_file->GetSectionList ();
- if (section_list)
- {
- uint32_t num_sections = section_list->GetSize();
- for (uint32_t i=0; i<num_sections; ++i)
- {
- SectionSP section_sp (section_list->GetSectionAtIndex (i));
- if (section_sp)
- {
- const addr_t new_section_load_addr = section_sp->GetFileAddress ();
- const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp);
- if (old_section_load_addr == LLDB_INVALID_ADDRESS ||
- old_section_load_addr != new_section_load_addr)
- {
- if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress ()))
- changed = true;
- }
- }
- }
- }
- }
- }
- return changed;
-}
-
//----------------------------------------------------------------------
// Update the load addresses for all segments in MODULE using the
// updated INFO that is passed in.
@@ -428,8 +457,8 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoad
std::vector<uint32_t> inaccessible_segment_indexes;
// We now know the slide amount, so go through all sections
// and update the load addresses with the correct values.
- uint32_t num_segments = info.segments.size();
- for (uint32_t i=0; i<num_segments; ++i)
+ const size_t num_segments = info.segments.size();
+ for (size_t i=0; i<num_segments; ++i)
{
// Only load a segment if it has protections. Things like
// __PAGEZERO don't have any protections, and they shouldn't
@@ -464,11 +493,10 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoad
else
{
Host::SystemLog (Host::eSystemLogWarning,
- "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n",
+ "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
(uint64_t)new_section_load_addr,
- image_object_file->GetFileSpec().GetDirectory().AsCString(),
- image_object_file->GetFileSpec().GetFilename().AsCString());
+ image_object_file->GetFileSpec().GetPath().c_str());
}
}
}
@@ -504,6 +532,14 @@ DynamicLoaderMacOSXDYLD::UpdateImageLoad
}
}
}
+ // We might have an in memory image that was loaded as soon as it was created
+ if (info.load_stop_id == m_process->GetStopID())
+ changed = true;
+ else if (changed)
+ {
+ // Update the stop ID when this library was updated
+ info.load_stop_id = m_process->GetStopID();
+ }
return changed;
}
@@ -523,8 +559,8 @@ DynamicLoaderMacOSXDYLD::UnloadImageLoad
SectionList *section_list = image_object_file->GetSectionList ();
if (section_list)
{
- uint32_t num_segments = info.segments.size();
- for (uint32_t i=0; i<num_segments; ++i)
+ const size_t num_segments = info.segments.size();
+ for (size_t i=0; i<num_segments; ++i)
{
SectionSP section_sp(section_list->FindSectionByName(info.segments[i].name));
if (section_sp)
@@ -536,10 +572,9 @@ DynamicLoaderMacOSXDYLD::UnloadImageLoad
else
{
Host::SystemLog (Host::eSystemLogWarning,
- "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n",
+ "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n",
info.segments[i].name.AsCString("<invalid>"),
- image_object_file->GetFileSpec().GetDirectory().AsCString(),
- image_object_file->GetFileSpec().GetFilename().AsCString());
+ image_object_file->GetFileSpec().GetPath().c_str());
}
}
}
@@ -653,7 +688,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInf
uint8_t buf[256];
DataExtractor data (buf, sizeof(buf), byte_order, addr_size);
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
const size_t count_v2 = sizeof (uint32_t) + // version
sizeof (uint32_t) + // infoArrayCount
@@ -676,9 +711,11 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInf
addr_size + // errorClientOfDylibPath
addr_size + // errorTargetDylibPath
addr_size; // errorSymbol
- assert (sizeof (buf) >= count_v11);
+ const size_t count_v13 = count_v11 +
+ addr_size + // sharedCacheSlide
+ sizeof (uuid_t); // sharedCacheUUID
+ assert (sizeof (buf) >= count_v13);
- int count;
Error error;
if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4)
{
@@ -705,10 +742,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInf
return false;
}
- if (m_dyld_all_image_infos.version >= 11)
- count = count_v11;
- else
- count = count_v2;
+ const size_t count = (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2;
const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error);
if (bytes_read == count)
@@ -759,7 +793,7 @@ bool
DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
{
DYLDImageInfo::collection image_infos;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf ("Adding %d modules.\n", image_infos_count);
@@ -784,14 +818,16 @@ DynamicLoaderMacOSXDYLD::AddModulesUsing
{
// Now add these images to the main list.
ModuleList loaded_module_list;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Target &target = m_process->GetTarget();
+ ModuleList& target_images = target.GetImages();
for (uint32_t idx = 0; idx < image_infos.size(); ++idx)
{
if (log)
{
- log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address);
- image_infos[idx].PutToLog (log.get());
+ log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
+ image_infos[idx].PutToLog (log);
}
m_dyld_image_infos.push_back(image_infos[idx]);
@@ -813,26 +849,31 @@ DynamicLoaderMacOSXDYLD::AddModulesUsing
Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get();
if (commpage_section)
{
- ModuleList& target_images = m_process->GetTarget().GetImages();
ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ());
module_spec.GetObjectName() = commpage_dbstr;
ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec));
if (!commpage_image_module_sp)
{
- module_spec.SetObjectOffset (objfile->GetOffset() + commpage_section->GetFileOffset());
- commpage_image_module_sp = m_process->GetTarget().GetSharedModule (module_spec);
+ module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset());
+ commpage_image_module_sp = target.GetSharedModule (module_spec);
if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL)
{
- const bool add_image_to_target = true;
- const bool load_image_sections_in_target = false;
commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec,
- image_infos[idx].address,
- add_image_to_target,
- load_image_sections_in_target);
+ image_infos[idx].address);
+ // Always load a memory image right away in the target in case
+ // we end up trying to read the symbol table from memory... The
+ // __LINKEDIT will need to be mapped so we can figure out where
+ // the symbol table bits are...
+ bool changed = false;
+ UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]);
+ target.GetImages().Append(commpage_image_module_sp);
+ if (changed)
+ {
+ image_infos[idx].load_stop_id = m_process->GetStopID();
+ loaded_module_list.AppendIfNeeded (commpage_image_module_sp);
+ }
}
}
- if (commpage_image_module_sp)
- UpdateCommPageLoadAddress (commpage_image_module_sp.get());
}
}
}
@@ -844,6 +885,7 @@ DynamicLoaderMacOSXDYLD::AddModulesUsing
// shared libraries each time.
if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx]))
{
+ target_images.AppendIfNeeded(image_module_sp);
loaded_module_list.AppendIfNeeded (image_module_sp);
}
}
@@ -880,7 +922,7 @@ bool
DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count)
{
DYLDImageInfo::collection image_infos;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Mutex::Locker locker(m_mutex);
if (m_process->GetStopID() == m_dyld_image_infos_stop_id)
@@ -902,8 +944,8 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUs
{
if (log)
{
- log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address);
- image_infos[idx].PutToLog (log.get());
+ log->Printf ("Removing module at address=0x%16.16" PRIx64 ".", image_infos[idx].address);
+ image_infos[idx].PutToLog (log);
}
// Remove this image_infos from the m_all_image_infos. We do the comparision by address
@@ -936,7 +978,7 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUs
if (log)
{
log->Printf ("Could not find module for unloading info entry:");
- image_infos[idx].PutToLog(log.get());
+ image_infos[idx].PutToLog(log);
}
}
@@ -952,7 +994,7 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUs
if (log)
{
log->Printf ("Could not find image_info entry for unloading image:");
- image_infos[idx].PutToLog(log.get());
+ image_infos[idx].PutToLog(log);
}
}
}
@@ -963,7 +1005,7 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUs
log->PutCString("Unloaded:");
unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload");
}
- m_process->GetTarget().ModulesDidUnload (unloaded_module_list);
+ m_process->GetTarget().GetImages().Remove (unloaded_module_list);
}
m_dyld_image_infos_stop_id = m_process->GetStopID();
return true;
@@ -987,7 +1029,7 @@ DynamicLoaderMacOSXDYLD::ReadImageInfos
error);
if (bytes_read == count)
{
- uint32_t info_data_offset = 0;
+ lldb::offset_t info_data_offset = 0;
DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), endian, addr_size);
for (int i = 0; i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); i++)
{
@@ -1022,7 +1064,7 @@ DynamicLoaderMacOSXDYLD::ReadImageInfos
bool
DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos ()
{
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
Mutex::Locker locker(m_mutex);
if (m_process->GetStopID() == m_dyld_image_infos_stop_id
@@ -1046,7 +1088,7 @@ DynamicLoaderMacOSXDYLD::InitializeFromA
if (!AddModulesUsingImageInfosAddress (m_dyld_all_image_infos.dylib_info_addr,
m_dyld_all_image_infos.dylib_info_count))
{
- DEBUG_PRINTF( "unable to read all data for all_dylib_infos.");
+ DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos.");
m_dyld_image_infos.clear();
}
}
@@ -1057,7 +1099,7 @@ DynamicLoaderMacOSXDYLD::InitializeFromA
// to an equivalent version. We don't want it to stay in the target's module list or it will confuse
// us, so unload it here.
Target &target = m_process->GetTarget();
- ModuleList &target_modules = target.GetImages();
+ const ModuleList &target_modules = target.GetImages();
ModuleList not_loaded_modules;
Mutex::Locker modules_locker(target_modules.GetMutex());
@@ -1079,7 +1121,7 @@ DynamicLoaderMacOSXDYLD::InitializeFromA
if (not_loaded_modules.GetSize() != 0)
{
- target.ModulesDidUnload(not_loaded_modules);
+ target.GetImages().Remove(not_loaded_modules);
}
return true;
@@ -1105,7 +1147,7 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader
error);
if (bytes_read == sizeof(llvm::MachO::mach_header))
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
::memset (header, 0, sizeof(llvm::MachO::mach_header));
// Get the magic byte unswapped so we can figure out what we are dealing with
@@ -1167,7 +1209,7 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader
uint32_t
DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker)
{
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
uint32_t cmd_idx;
Segment segment;
dylib_info.Clear (true);
@@ -1180,7 +1222,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadComman
if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command)))
{
llvm::MachO::load_command load_cmd;
- uint32_t load_cmd_offset = offset;
+ lldb::offset_t load_cmd_offset = offset;
load_cmd.cmd = data.GetU32 (&offset);
load_cmd.cmdsize = data.GetU32 (&offset);
switch (load_cmd.cmd)
@@ -1214,7 +1256,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadComman
case llvm::MachO::LoadCommandDynamicLinkerIdent:
if (lc_id_dylinker)
{
- uint32_t name_offset = load_cmd_offset + data.GetU32 (&offset);
+ const lldb::offset_t name_offset = load_cmd_offset + data.GetU32 (&offset);
const char *path = data.PeekCStr (name_offset);
lc_id_dylinker->SetFile (path, true);
}
@@ -1267,7 +1309,6 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfo
bool update_executable)
{
uint32_t exe_idx = UINT32_MAX;
- LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER));
// Read any UUID values that we can get
for (uint32_t i = 0; i < infos_count; i++)
{
@@ -1285,32 +1326,18 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfo
}
}
+ Target &target = m_process->GetTarget();
+
if (exe_idx < image_infos.size())
{
const bool can_create = true;
ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL));
- if (!exe_module_sp)
- {
- ArchSpec exe_arch_spec (image_infos[exe_idx].GetArchitecture ());
- ModuleSpec module_spec (image_infos[exe_idx].file_spec,
- image_infos[exe_idx].GetArchitecture ());
- module_spec.GetUUID() = image_infos[exe_idx].uuid;
- exe_module_sp = m_process->GetTarget().GetSharedModule (module_spec);
- if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
- {
- const bool add_image_to_target = true;
- const bool load_image_sections_in_target = false;
- exe_module_sp = m_process->ReadModuleFromMemory (image_infos[exe_idx].file_spec,
- image_infos[exe_idx].address,
- add_image_to_target,
- load_image_sections_in_target);
- }
- }
-
if (exe_module_sp)
{
- if (exe_module_sp.get() != m_process->GetTarget().GetExecutableModulePointer())
+ UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]);
+
+ if (exe_module_sp.get() != target.GetExecutableModulePointer())
{
// Don't load dependent images since we are in dyld where we will know
// and find out about all images that are loaded
@@ -1371,12 +1398,12 @@ DynamicLoaderMacOSXDYLD::Segment::PutToL
if (log)
{
if (slide == 0)
- log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)",
+ log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")",
name.AsCString(""),
vmaddr + slide,
vmaddr + slide + vmsize);
else
- log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx",
+ log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64,
name.AsCString(""),
vmaddr + slide,
vmaddr + slide + vmsize,
@@ -1411,42 +1438,38 @@ DynamicLoaderMacOSXDYLD::DYLDImageInfo::
{
if (u)
{
- log->Printf("\t modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s' (UNLOADED)",
+ log->Printf("\t modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)",
mod_date,
u[ 0], u[ 1], u[ 2], u[ 3],
u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11],
u[12], u[13], u[14], u[15],
- file_spec.GetDirectory().AsCString(),
- file_spec.GetFilename().AsCString());
+ file_spec.GetPath().c_str());
}
else
- log->Printf("\t modtime=0x%8.8llx path='%s/%s' (UNLOADED)",
+ log->Printf("\t modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)",
mod_date,
- file_spec.GetDirectory().AsCString(),
- file_spec.GetFilename().AsCString());
+ file_spec.GetPath().c_str());
}
else
{
if (u)
{
- log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s/%s'",
+ log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'",
address,
mod_date,
u[ 0], u[ 1], u[ 2], u[ 3],
u[ 4], u[ 5], u[ 6], u[ 7],
u[ 8], u[ 9], u[10], u[11],
u[12], u[13], u[14], u[15],
- file_spec.GetDirectory().AsCString(),
- file_spec.GetFilename().AsCString());
+ file_spec.GetPath().c_str());
}
else
{
- log->Printf("\taddress=0x%16.16llx modtime=0x%8.8llx path='%s/%s'",
+ log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'",
address,
mod_date,
- file_spec.GetDirectory().AsCString(),
- file_spec.GetFilename().AsCString());
+ file_spec.GetPath().c_str());
}
for (uint32_t i=0; i<segments.size(); ++i)
@@ -1465,7 +1488,7 @@ DynamicLoaderMacOSXDYLD::PutToLog(Log *l
return;
Mutex::Locker locker(m_mutex);
- log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8llx, notify=0x%8.8llx }",
+ log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64 ", notify=0x%8.8" PRIx64 " }",
m_dyld_all_image_infos.version,
m_dyld_all_image_infos.dylib_info_count,
(uint64_t)m_dyld_all_image_infos.dylib_info_addr,
@@ -1507,6 +1530,7 @@ DynamicLoaderMacOSXDYLD::SetNotification
{
Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get();
dyld_break->SetCallback (DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, this, true);
+ dyld_break->SetBreakpointKind ("shared-library-event");
m_break_id = dyld_break->GetID();
}
}
@@ -1550,9 +1574,6 @@ DynamicLoaderMacOSXDYLD::PrivateProcessS
case eStateCrashed:
case eStateSuspended:
break;
-
- default:
- break;
}
}
@@ -1571,7 +1592,7 @@ DynamicLoaderMacOSXDYLD::GetStepThroughT
StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get();
const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol);
Symbol *current_symbol = current_context.symbol;
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (current_symbol != NULL)
{
@@ -1583,7 +1604,7 @@ DynamicLoaderMacOSXDYLD::GetStepThroughT
{
SymbolContextList target_symbols;
TargetSP target_sp (thread.CalculateTarget());
- ModuleList &images = target_sp->GetImages();
+ const ModuleList &images = target_sp->GetImages();
images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols);
@@ -1593,6 +1614,8 @@ DynamicLoaderMacOSXDYLD::GetStepThroughT
// For now, just turn this off.
// bool orig_is_resolver = (current_symbol->GetFlags() & MACH_O_N_SYMBOL_RESOLVER) == MACH_O_N_SYMBOL_RESOLVER;
+ // FIXME: Actually that isn't true, the N_SYMBOL_RESOLVER bit is only valid in .o files. You can't use
+ // the symbol flags to tell whether something is a symbol resolver in a linked image.
bool orig_is_resolver = false;
if (num_original_symbols > 0)
@@ -1737,10 +1760,11 @@ DynamicLoaderMacOSXDYLD::Terminate()
}
-const char *
+lldb_private::ConstString
DynamicLoaderMacOSXDYLD::GetPluginNameStatic()
{
- return "dynamic-loader.macosx-dyld";
+ static ConstString g_name("macosx-dyld");
+ return g_name;
}
const char *
@@ -1753,15 +1777,9 @@ DynamicLoaderMacOSXDYLD::GetPluginDescri
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
DynamicLoaderMacOSXDYLD::GetPluginName()
{
- return "DynamicLoaderMacOSXDYLD";
-}
-
-const char *
-DynamicLoaderMacOSXDYLD::GetShortPluginName()
-{
return GetPluginNameStatic();
}
@@ -1771,3 +1789,50 @@ DynamicLoaderMacOSXDYLD::GetPluginVersio
return 1;
}
+uint32_t
+DynamicLoaderMacOSXDYLD::AddrByteSize()
+{
+ switch (m_dyld.header.magic)
+ {
+ case llvm::MachO::HeaderMagic32:
+ case llvm::MachO::HeaderMagic32Swapped:
+ return 4;
+
+ case llvm::MachO::HeaderMagic64:
+ case llvm::MachO::HeaderMagic64Swapped:
+ return 8;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+lldb::ByteOrder
+DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic (uint32_t magic)
+{
+ switch (magic)
+ {
+ case llvm::MachO::HeaderMagic32:
+ case llvm::MachO::HeaderMagic64:
+ return lldb::endian::InlHostByteOrder();
+
+ case llvm::MachO::HeaderMagic32Swapped:
+ case llvm::MachO::HeaderMagic64Swapped:
+ if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
+ return lldb::eByteOrderLittle;
+ else
+ return lldb::eByteOrderBig;
+
+ default:
+ break;
+ }
+ return lldb::eByteOrderInvalid;
+}
+
+lldb::ByteOrder
+DynamicLoaderMacOSXDYLD::DYLDImageInfo::GetByteOrder()
+{
+ return DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header.magic);
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h Thu Jun 6 19:06:43 2013
@@ -37,7 +37,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -62,6 +62,9 @@ public:
virtual void
DidLaunch ();
+ virtual bool
+ ProcessDidExec ();
+
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
bool stop_others);
@@ -77,12 +80,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -118,45 +118,10 @@ protected:
lldb::user_id_t break_loc_id);
uint32_t
- AddrByteSize()
- {
- switch (m_dyld.header.magic)
- {
- case llvm::MachO::HeaderMagic32:
- case llvm::MachO::HeaderMagic32Swapped:
- return 4;
-
- case llvm::MachO::HeaderMagic64:
- case llvm::MachO::HeaderMagic64Swapped:
- return 8;
-
- default:
- break;
- }
- return 0;
- }
+ AddrByteSize();
static lldb::ByteOrder
- GetByteOrderFromMagic (uint32_t magic)
- {
- switch (magic)
- {
- case llvm::MachO::HeaderMagic32:
- case llvm::MachO::HeaderMagic64:
- return lldb::endian::InlHostByteOrder();
-
- case llvm::MachO::HeaderMagic32Swapped:
- case llvm::MachO::HeaderMagic64Swapped:
- if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig)
- return lldb::eByteOrderLittle;
- else
- return lldb::eByteOrderBig;
-
- default:
- break;
- }
- return lldb::eByteOrderInvalid;
- }
+ GetByteOrderFromMagic (uint32_t magic);
bool
ReadMachHeader (lldb::addr_t addr,
@@ -210,6 +175,7 @@ protected:
lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros
llvm::MachO::mach_header header; // The mach header for this image
std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior)
+ uint32_t load_stop_id; // The process stop ID that the sections for this image were loadeded
DYLDImageInfo() :
address(LLDB_INVALID_ADDRESS),
@@ -218,7 +184,8 @@ protected:
file_spec(),
uuid(),
header(),
- segments()
+ segments(),
+ load_stop_id(0)
{
}
@@ -235,6 +202,7 @@ protected:
}
uuid.Clear();
segments.clear();
+ load_stop_id = 0;
}
bool
@@ -269,26 +237,7 @@ protected:
}
lldb::ByteOrder
- GetByteOrder()
- {
- switch (header.magic)
- {
- case llvm::MachO::HeaderMagic32: // MH_MAGIC
- case llvm::MachO::HeaderMagic64: // MH_MAGIC_64
- return lldb::endian::InlHostByteOrder();
-
- case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM
- case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64
- if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle)
- return lldb::eByteOrderBig;
- else
- return lldb::eByteOrderLittle;
- default:
- assert (!"invalid header.magic value");
- break;
- }
- return lldb::endian::InlHostByteOrder();
- }
+ GetByteOrder();
lldb_private::ArchSpec
GetArchitecture () const
@@ -367,7 +316,7 @@ protected:
DYLDImageInfo& info);
lldb::ModuleSP
- FindTargetModuleForDYLDImageInfo (const DYLDImageInfo &image_info,
+ FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info,
bool can_create,
bool *did_create_ptr);
@@ -409,9 +358,6 @@ protected:
bool update_executable);
bool
- UpdateCommPageLoadAddress (lldb_private::Module *module);
-
- bool
ReadImageInfos (lldb::addr_t image_infos_addr,
uint32_t image_infos_count,
DYLDImageInfo::collection &image_infos);
@@ -426,6 +372,7 @@ protected:
uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for
mutable lldb_private::Mutex m_mutex;
lldb_private::Process::Notifications m_notification_callbacks;
+ bool m_process_image_addr_is_all_images_infos;
private:
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXDYLD);
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp Thu Jun 6 19:06:43 2013
@@ -26,21 +26,25 @@ using namespace lldb_private;
static bool
GetMaxU64(DataExtractor &data,
- uint32_t *offset, uint64_t *value, unsigned int byte_size)
-{
- uint32_t saved_offset = *offset;
- *value = data.GetMaxU64(offset, byte_size);
- return *offset != saved_offset;
+ lldb::offset_t *offset_ptr,
+ uint64_t *value,
+ unsigned int byte_size)
+{
+ lldb::offset_t saved_offset = *offset_ptr;
+ *value = data.GetMaxU64(offset_ptr, byte_size);
+ return *offset_ptr != saved_offset;
}
static bool
-ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry,
- uint32_t *offset, unsigned int byte_size)
+ParseAuxvEntry(DataExtractor &data,
+ AuxVector::Entry &entry,
+ lldb::offset_t *offset_ptr,
+ unsigned int byte_size)
{
- if (!GetMaxU64(data, offset, &entry.type, byte_size))
+ if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size))
return false;
- if (!GetMaxU64(data, offset, &entry.value, byte_size))
+ if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size))
return false;
return true;
@@ -57,7 +61,7 @@ void
AuxVector::ParseAuxv(DataExtractor &data)
{
const unsigned int byte_size = m_process->GetAddressByteSize();
- uint32_t offset = 0;
+ lldb::offset_t offset = 0;
for (;;)
{
@@ -80,7 +84,7 @@ AuxVector::AuxVector(Process *process)
: m_process(process)
{
DataExtractor data;
- LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
data.SetData(GetAuxvData());
data.SetByteOrder(m_process->GetByteOrder());
@@ -105,7 +109,7 @@ AuxVector::FindEntry(EntryType type) con
}
void
-AuxVector::DumpToLog(LogSP log) const
+AuxVector::DumpToLog(Log *log) const
{
if (!log)
return;
@@ -113,7 +117,7 @@ AuxVector::DumpToLog(LogSP log) const
log->PutCString("AuxVector: ");
for (iterator I = begin(); I != end(); ++I)
{
- log->Printf(" %s [%llu]: %llx", GetEntryName(*I), I->type, I->value);
+ log->Printf(" %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type, I->value);
}
}
@@ -125,10 +129,6 @@ AuxVector::GetEntryName(EntryType type)
#define ENTRY_NAME(_type) _type: name = #_type
switch (type)
{
- default:
- name = "unkown";
- break;
-
case ENTRY_NAME(AT_NULL); break;
case ENTRY_NAME(AT_IGNORE); break;
case ENTRY_NAME(AT_EXECFD); break;
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h Thu Jun 6 19:06:43 2013
@@ -81,7 +81,7 @@ public:
GetEntryName(EntryType type);
void
- DumpToLog(lldb::LogSP log) const;
+ DumpToLog(lldb_private::Log *log) const;
private:
lldb_private::Process *m_process;
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp Thu Jun 6 19:06:43 2013
@@ -13,6 +13,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -58,7 +59,12 @@ DYLDRendezvous::DYLDRendezvous(Process *
m_removed_soentries()
{
// Cache a copy of the executable path
- m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+ if (m_process)
+ {
+ Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
+ if (exe_mod)
+ exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+ }
}
bool
@@ -294,7 +300,7 @@ DYLDRendezvous::ReadSOEntryFromMemory(ll
}
void
-DYLDRendezvous::DumpToLog(LogSP log) const
+DYLDRendezvous::DumpToLog(Log *log) const
{
int state = GetState();
@@ -302,11 +308,11 @@ DYLDRendezvous::DumpToLog(LogSP log) con
return;
log->PutCString("DYLDRendezvous:");
- log->Printf(" Address: %llx", GetRendezvousAddress());
- log->Printf(" Version: %d", GetVersion());
- log->Printf(" Link : %llx", GetLinkMapAddress());
- log->Printf(" Break : %llx", GetBreakAddress());
- log->Printf(" LDBase : %llx", GetLDBase());
+ log->Printf(" Address: %" PRIx64, GetRendezvousAddress());
+ log->Printf(" Version: %" PRIu64, GetVersion());
+ log->Printf(" Link : %" PRIx64, GetLinkMapAddress());
+ log->Printf(" Break : %" PRIx64, GetBreakAddress());
+ log->Printf(" LDBase : %" PRIx64, GetLDBase());
log->Printf(" State : %s",
(state == eConsistent) ? "consistent" :
(state == eAdd) ? "add" :
@@ -321,10 +327,10 @@ DYLDRendezvous::DumpToLog(LogSP log) con
for (int i = 1; I != E; ++I, ++i)
{
log->Printf("\n SOEntry [%d] %s", i, I->path.c_str());
- log->Printf(" Base : %llx", I->base_addr);
- log->Printf(" Path : %llx", I->path_addr);
- log->Printf(" Dyn : %llx", I->dyn_addr);
- log->Printf(" Next : %llx", I->next);
- log->Printf(" Prev : %llx", I->prev);
+ log->Printf(" Base : %" PRIx64, I->base_addr);
+ log->Printf(" Path : %" PRIx64, I->path_addr);
+ log->Printf(" Dyn : %" PRIx64, I->dyn_addr);
+ log->Printf(" Next : %" PRIx64, I->next);
+ log->Printf(" Prev : %" PRIx64, I->prev);
}
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h Thu Jun 6 19:06:43 2013
@@ -73,7 +73,7 @@ public:
GetRendezvousAddress() const { return m_rendezvous_addr; }
/// @returns the version of the rendezvous protocol being used.
- int
+ uint64_t
GetVersion() const { return m_current.version; }
/// @returns address in the inferiors address space containing the linked
@@ -92,7 +92,7 @@ public:
GetBreakAddress() const { return m_current.brk; }
/// Returns the current state of the rendezvous structure.
- int
+ uint64_t
GetState() const { return m_current.state; }
/// @returns the base address of the runtime linker in the inferiors address
@@ -111,7 +111,7 @@ public:
ModulesDidUnload() const { return !m_removed_soentries.empty(); }
void
- DumpToLog(lldb::LogSP log) const;
+ DumpToLog(lldb_private::Log *log) const;
/// @brief Constants describing the state of the rendezvous.
///
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Thu Jun 6 19:06:43 2013
@@ -12,6 +12,10 @@
// Other libraries and framework includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -36,22 +40,17 @@ DynamicLoaderPOSIXDYLD::Terminate()
{
}
-const char *
+lldb_private::ConstString
DynamicLoaderPOSIXDYLD::GetPluginName()
{
- return "DynamicLoaderPOSIXDYLD";
-}
-
-const char *
-DynamicLoaderPOSIXDYLD::GetShortPluginName()
-{
- return "linux-dyld";
+ return GetPluginNameStatic();
}
-const char *
+lldb_private::ConstString
DynamicLoaderPOSIXDYLD::GetPluginNameStatic()
{
- return "dynamic-loader.linux-dyld";
+ static ConstString g_name("linux-dyld");
+ return g_name;
}
const char *
@@ -94,7 +93,7 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOS
m_rendezvous(process),
m_load_offset(LLDB_INVALID_ADDRESS),
m_entry_point(LLDB_INVALID_ADDRESS),
- m_auxv(NULL)
+ m_auxv()
{
}
@@ -110,7 +109,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
m_auxv.reset(new AuxVector(m_process));
- executable = m_process->GetTarget().GetExecutableModule();
+ executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
@@ -131,7 +130,7 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
m_auxv.reset(new AuxVector(m_process));
- executable = m_process->GetTarget().GetExecutableModule();
+ executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
@@ -144,6 +143,46 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
}
}
+ModuleSP
+DynamicLoaderPOSIXDYLD::GetTargetExecutable()
+{
+ Target &target = m_process->GetTarget();
+ ModuleSP executable = target.GetExecutableModule();
+
+ if (executable.get())
+ {
+ if (executable->GetFileSpec().Exists())
+ {
+ ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture());
+ ModuleSP module_sp (new Module (module_spec));
+
+ // Check if the executable has changed and set it to the target executable if they differ.
+ if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
+ {
+ if (module_sp->GetUUID() != executable->GetUUID())
+ executable.reset();
+ }
+ else if (executable->FileHasChanged())
+ {
+ executable.reset();
+ }
+
+ if (!executable.get())
+ {
+ executable = target.GetSharedModule(module_spec);
+ if (executable.get() != target.GetExecutableModulePointer())
+ {
+ // Don't load dependent images since we are in dyld where we will know
+ // and find out about all images that are loaded
+ const bool get_dependent_images = false;
+ target.SetExecutableModule(executable, get_dependent_images);
+ }
+ }
+ }
+ }
+ return executable;
+}
+
Error
DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
{
@@ -198,6 +237,7 @@ DynamicLoaderPOSIXDYLD::ProbeEntry()
entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
entry_break->SetCallback(EntryBreakpointHit, this, true);
+ entry_break->SetBreakpointKind("shared-library-event");
}
// The runtime linker has run and initialized the rendezvous structure once the
@@ -229,6 +269,7 @@ DynamicLoaderPOSIXDYLD::SetRendezvousBre
break_addr = m_rendezvous.GetBreakAddress();
dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get();
dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+ dyld_break->SetBreakpointKind ("shared-library-event");
}
bool
@@ -267,9 +308,8 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
FileSpec file(I->path.c_str(), true);
ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
if (module_sp.get())
- new_modules.Append(module_sp);
+ loaded_modules.AppendIfNeeded(module_sp);
}
- m_process->GetTarget().ModulesDidLoad(new_modules);
}
if (m_rendezvous.ModulesDidUnload())
@@ -286,7 +326,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
if (module_sp.get())
old_modules.Append(module_sp);
}
- m_process->GetTarget().ModulesDidUnload(old_modules);
+ loaded_modules.Remove(old_modules);
}
}
@@ -308,7 +348,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTr
SymbolContextList target_symbols;
Target &target = thread.GetProcess()->GetTarget();
- ModuleList &images = target.GetImages();
+ const ModuleList &images = target.GetImages();
images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
size_t num_targets = target_symbols.GetSize();
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h Thu Jun 6 19:06:43 2013
@@ -30,7 +30,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -64,12 +64,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -93,7 +90,7 @@ protected:
lldb::addr_t m_entry_point;
/// Auxiliary vector of the inferior process.
- std::auto_ptr<AuxVector> m_auxv;
+ std::unique_ptr<AuxVector> m_auxv;
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
@@ -158,6 +155,11 @@ protected:
lldb::addr_t
GetEntryPoint();
+ /// Checks to see if the target module has changed, updates the target
+ /// accordingly and returns the target executable module.
+ lldb::ModuleSP
+ GetTargetExecutable();
+
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
};
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp Thu Jun 6 19:06:43 2013
@@ -9,6 +9,8 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
#include "DynamicLoaderStatic.h"
@@ -93,10 +95,13 @@ DynamicLoaderStatic::DidLaunch ()
void
DynamicLoaderStatic::LoadAllImagesAtFileAddresses ()
{
- ModuleList &module_list = m_process->GetTarget().GetImages();
+ const ModuleList &module_list = m_process->GetTarget().GetImages();
ModuleList loaded_module_list;
+ // Disable JIT for static dynamic loader targets
+ m_process->SetCanJIT(false);
+
Mutex::Locker mutex_locker(module_list.GetMutex());
const size_t num_modules = module_list.GetSize();
@@ -141,8 +146,7 @@ DynamicLoaderStatic::LoadAllImagesAtFile
}
}
- if (loaded_module_list.GetSize())
- m_process->GetTarget().ModulesDidLoad (loaded_module_list);
+ m_process->GetTarget().ModulesDidLoad (loaded_module_list);
}
ThreadPlanSP
@@ -174,10 +178,11 @@ DynamicLoaderStatic::Terminate()
}
-const char *
+lldb_private::ConstString
DynamicLoaderStatic::GetPluginNameStatic()
{
- return "dynamic-loader.static";
+ static ConstString g_name("static");
+ return g_name;
}
const char *
@@ -190,15 +195,9 @@ DynamicLoaderStatic::GetPluginDescriptio
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
DynamicLoaderStatic::GetPluginName()
{
- return "DynamicLoaderStatic";
-}
-
-const char *
-DynamicLoaderStatic::GetShortPluginName()
-{
return GetPluginNameStatic();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h Thu Jun 6 19:06:43 2013
@@ -37,7 +37,7 @@ public:
static void
Terminate();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic();
static const char *
@@ -72,12 +72,9 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
Modified: lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Thu Jun 6 19:06:43 2013
@@ -16,6 +16,8 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/OptionValueArray.h"
+#include "lldb/Interpreter/OptionValueDictionary.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "Plugins/Process/Utility/ARMDefines.h"
@@ -23,7 +25,7 @@
#include "Utility/ARM_DWARF_Registers.h"
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
- // and CountTrailingZeros_32 function
+ // and countTrailingZeros function
using namespace lldb;
using namespace lldb_private;
@@ -45,7 +47,7 @@ using namespace lldb_private;
static uint32_t
CountITSize (uint32_t ITMask) {
// First count the trailing zeros of the IT mask.
- uint32_t TZ = llvm::CountTrailingZeros_32(ITMask);
+ uint32_t TZ = llvm::countTrailingZeros(ITMask);
if (TZ > 3)
{
printf("Encoding error: IT Mask '0000'\n");
@@ -172,10 +174,11 @@ EmulateInstructionARM::Terminate ()
PluginManager::UnregisterPlugin (CreateInstance);
}
-const char *
+ConstString
EmulateInstructionARM::GetPluginNameStatic ()
{
- return "lldb.emulate-instruction.arm";
+ static ConstString g_name("arm");
+ return g_name;
}
const char *
@@ -191,14 +194,14 @@ EmulateInstructionARM::CreateInstance (c
{
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
- std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+ std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
if (emulate_insn_ap.get())
return emulate_insn_ap.release();
}
else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
{
- std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+ std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
if (emulate_insn_ap.get())
return emulate_insn_ap.release();
@@ -12779,7 +12782,7 @@ EmulateInstructionARM::GetThumbOpcodeFor
{ 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
{ 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
{ 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
- { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+ { 0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
{ 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
//----------------------------------------------------------------------
@@ -12999,7 +13002,6 @@ EmulateInstructionARM::CurrentCond (cons
{
switch (m_opcode_mode)
{
- default:
case eModeInvalid:
break;
@@ -13611,9 +13613,7 @@ EmulateInstructionARM::CreateFunctionEnt
// All other registers are the same.
unwind_plan.SetSourceName ("EmulateInstructionARM");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
return true;
}
-
-
-
-
Modified: lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulateInstructionARM.h Thu Jun 6 19:06:43 2013
@@ -11,8 +11,8 @@
#define lldb_EmulateInstructionARM_h_
#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
-#include "lldb/Interpreter/NamedOptionValue.h"
#include "Plugins/Process/Utility/ARMDefines.h"
namespace lldb_private {
@@ -68,7 +68,7 @@ public:
static void
Terminate ();
- static const char *
+ static lldb_private::ConstString
GetPluginNameStatic ();
static const char *
@@ -90,22 +90,13 @@ public:
case eInstructionTypeAll:
return false;
-
- default:
- break;
}
return false;
}
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName()
{
- return "EmulateInstructionARM";
- }
-
- virtual const char *
- GetShortPluginName()
- {
return GetPluginNameStatic();
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.cpp Thu Jun 6 19:06:43 2013
@@ -11,6 +11,8 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Interpreter/OptionValueArray.h"
+#include "lldb/Interpreter/OptionValueDictionary.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/RegisterContext.h"
Modified: lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/Instruction/ARM/EmulationStateARM.h Thu Jun 6 19:06:43 2013
@@ -14,7 +14,6 @@
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Opcode.h"
-#include "lldb/Interpreter/NamedOptionValue.h"
class EmulationStateARM {
public:
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp Thu Jun 6 19:06:43 2013
@@ -19,6 +19,8 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@@ -30,9 +32,6 @@
using namespace lldb;
using namespace lldb_private;
-static const char *pluginName = "ItaniumABILanguageRuntime";
-static const char *pluginDesc = "Itanium ABI for the C++ language";
-static const char *pluginShort = "language.itanium";
static const char *vtable_demangled_prefix = "vtable for ";
bool
@@ -57,6 +56,8 @@ ItaniumABILanguageRuntime::GetDynamicTyp
// start of the value object which holds the dynamic type.
//
+ class_type_or_name.Clear();
+
// Only a pointer or reference type can have a different dynamic and static type:
if (CouldHaveDynamicValue (in_value))
{
@@ -86,10 +87,10 @@ ItaniumABILanguageRuntime::GetDynamicTyp
return false;
}
- uint32_t offset_ptr = 0;
- lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
+ lldb::offset_t offset = 0;
+ lldb::addr_t vtable_address_point = data.GetAddress (&offset);
- if (offset_ptr == 0)
+ if (offset == 0)
return false;
// Now find the symbol that contains this address:
@@ -107,9 +108,9 @@ ItaniumABILanguageRuntime::GetDynamicTyp
const char *name = symbol->GetMangled().GetDemangledName().AsCString();
if (strstr(name, vtable_demangled_prefix) == name)
{
- LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
- log->Printf ("0x%16.16llx: static-type = '%s' has vtable symbol '%s'\n",
+ log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
original_ptr,
in_value.GetTypeName().GetCString(),
name);
@@ -147,14 +148,14 @@ ItaniumABILanguageRuntime::GetDynamicTyp
if (num_matches == 0)
{
if (log)
- log->Printf("0x%16.16llx: is not dynamic\n", original_ptr);
+ log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
return false;
}
if (num_matches == 1)
{
type_sp = class_types.GetTypeAtIndex(0);
if (log)
- log->Printf ("0x%16.16llx: static-type = '%s' has dynamic type: uid={0x%llx}, type-name='%s'\n",
+ log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
original_ptr,
in_value.GetTypeName().AsCString(),
type_sp->GetID(),
@@ -173,7 +174,7 @@ ItaniumABILanguageRuntime::GetDynamicTyp
if (type_sp)
{
if (log)
- log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types: uid={0x%llx}, type-name='%s'\n",
+ log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
original_ptr,
in_value.GetTypeName().AsCString(),
type_sp->GetID(),
@@ -190,7 +191,7 @@ ItaniumABILanguageRuntime::GetDynamicTyp
if (ClangASTContext::IsCXXClassType(type_sp->GetClangFullType()))
{
if (log)
- log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%llx}, type-name='%s'\n",
+ log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
original_ptr,
in_value.GetTypeName().AsCString(),
type_sp->GetID(),
@@ -204,7 +205,7 @@ ItaniumABILanguageRuntime::GetDynamicTyp
if (i == num_matches)
{
if (log)
- log->Printf ("0x%16.16llx: static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
+ log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
original_ptr,
in_value.GetTypeName().AsCString());
return false;
@@ -251,8 +252,8 @@ ItaniumABILanguageRuntime::GetDynamicTyp
return false;
}
- offset_ptr = 0;
- int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
+ offset = 0;
+ int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
// So the dynamic type is a value that starts at offset_to_top
// above the original address.
@@ -269,7 +270,7 @@ ItaniumABILanguageRuntime::GetDynamicTyp
}
}
- return false;
+ return class_type_or_name.IsEmpty() == false;
}
bool
@@ -302,8 +303,8 @@ ItaniumABILanguageRuntime::CreateInstanc
void
ItaniumABILanguageRuntime::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Itanium ABI for the C++ language",
CreateInstance);
}
@@ -313,19 +314,20 @@ ItaniumABILanguageRuntime::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+ItaniumABILanguageRuntime::GetPluginNameStatic()
+{
+ static ConstString g_name("itanium");
+ return g_name;
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
ItaniumABILanguageRuntime::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-ItaniumABILanguageRuntime::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
@@ -334,10 +336,6 @@ ItaniumABILanguageRuntime::GetPluginVers
return 1;
}
-static const char *exception_names[] = { "__cxa_begin_catch", "__cxa_throw", "__cxa_rethrow", "__cxa_allocate_exception"};
-static const int num_throw_names = 3;
-static const int num_expression_throw_names = 1;
-
BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
{
@@ -347,49 +345,70 @@ ItaniumABILanguageRuntime::CreateExcepti
BreakpointResolverSP
ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
{
- BreakpointResolverSP resolver_sp;
- static const int total_expressions = sizeof (exception_names)/sizeof (char *);
-
// One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
// anything better with predicting unwinding the expression parser does. So we have two forms of the exception
// breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
// The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
+ static const char *g_catch_name = "__cxa_begin_catch";
+ static const char *g_throw_name1 = "__cxa_throw";
+ static const char *g_throw_name2 = "__cxa_rethrow";
+ static const char *g_exception_throw_name = "__cxa_allocate_exception";
+ std::vector<const char *> exception_names;
+ exception_names.reserve(4);
+ if (catch_bp)
+ exception_names.push_back(g_catch_name);
+
+ if (throw_bp)
+ {
+ exception_names.push_back(g_throw_name1);
+ exception_names.push_back(g_throw_name2);
+ }
+
+ if (for_expressions)
+ exception_names.push_back(g_exception_throw_name);
- uint32_t num_expressions;
- if (catch_bp && throw_bp)
+ BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
+ exception_names.data(),
+ exception_names.size(),
+ eFunctionNameTypeBase,
+ eLazyBoolNo));
+
+ return resolver_sp;
+}
+
+
+
+lldb::SearchFilterSP
+ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
+{
+ Target &target = m_process->GetTarget();
+
+ if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
{
- if (for_expressions)
- num_expressions = total_expressions;
- else
- num_expressions = total_expressions - num_expression_throw_names;
-
- resolver_sp.reset (new BreakpointResolverName (bkpt,
- exception_names,
- num_expressions,
- eFunctionNameTypeBase,
- eLazyBoolNo));
+ // Limit the number of modules that are searched for these breakpoints for
+ // Apple binaries.
+ FileSpecList filter_modules;
+ filter_modules.Append(FileSpec("libc++abi.dylib", false));
+ filter_modules.Append(FileSpec("libSystem.B.dylib", false));
+ return target.GetSearchFilterForModuleList(&filter_modules);
}
- else if (throw_bp)
+ else
{
- if (for_expressions)
- num_expressions = num_throw_names - num_expression_throw_names;
- else
- num_expressions = num_throw_names;
-
- resolver_sp.reset (new BreakpointResolverName (bkpt,
- exception_names + 1,
- num_expressions,
- eFunctionNameTypeBase,
- eLazyBoolNo));
+ return LanguageRuntime::CreateExceptionSearchFilter();
}
- else if (catch_bp)
- resolver_sp.reset (new BreakpointResolverName (bkpt,
- exception_names,
- total_expressions - num_throw_names,
- eFunctionNameTypeBase,
- eLazyBoolNo));
+}
- return resolver_sp;
+lldb::BreakpointSP
+ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
+ bool throw_bp,
+ bool for_expressions,
+ bool is_internal)
+{
+ Target &target = m_process->GetTarget();
+ FileSpecList filter_modules;
+ BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
+ SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
+ return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
}
void
@@ -406,17 +425,16 @@ ItaniumABILanguageRuntime::SetExceptionB
// For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
// stop at exception allocation as well.
- if (!m_cxx_exception_bp_sp)
+ if (m_cxx_exception_bp_sp)
{
- Target &target = m_process->GetTarget();
-
- BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
- SearchFilterSP filter_sp = target.GetSearchFilterForModule(NULL);
-
- m_cxx_exception_bp_sp = target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
+ m_cxx_exception_bp_sp->SetEnabled (true);
}
else
- m_cxx_exception_bp_sp->SetEnabled (true);
+ {
+ m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
+ if (m_cxx_exception_bp_sp)
+ m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
+ }
}
@@ -426,7 +444,7 @@ ItaniumABILanguageRuntime::ClearExceptio
if (!m_process)
return;
- if (m_cxx_exception_bp_sp.get())
+ if (m_cxx_exception_bp_sp)
{
m_cxx_exception_bp_sp->SetEnabled (false);
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h Thu Jun 6 19:06:43 2013
@@ -52,15 +52,15 @@ namespace lldb_private {
static lldb_private::LanguageRuntime *
CreateInstance (Process *process, lldb::LanguageType language);
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual lldb_private::ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -72,14 +72,24 @@ namespace lldb_private {
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
-
- protected:
+
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+
+ virtual lldb::SearchFilterSP
+ CreateExceptionSearchFilter ();
- virtual lldb::BreakpointResolverSP
+ protected:
+
+ lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions);
+ lldb::BreakpointSP
+ CreateExceptionBreakpoint(bool catch_bp,
+ bool throw_bp,
+ bool for_expressions,
+ bool is_internal);
+
private:
ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead.
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp Thu Jun 6 19:06:43 2013
@@ -38,6 +38,8 @@
using namespace lldb;
using namespace lldb_private;
+#define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000
+
bool
AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj)
{
@@ -134,17 +136,19 @@ AppleObjCRuntime::GetObjectDescription (
lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
- bool unwind_on_error = true;
- bool try_all_threads = true;
- bool stop_others = true;
+ const bool unwind_on_error = true;
+ const bool try_all_threads = true;
+ const bool stop_others = true;
+ const bool ignore_breakpoints = true;
ExecutionResults results = func.ExecuteFunction (exe_ctx,
&wrapper_struct_addr,
error_stream,
stop_others,
- 0 /* no timeout */,
+ PO_FUNCTION_TIMEOUT_USEC /* 15 secs timeout */,
try_all_threads,
- unwind_on_error,
+ unwind_on_error,
+ ignore_breakpoints,
ret);
if (results != eExecutionCompleted)
{
@@ -168,12 +172,36 @@ AppleObjCRuntime::GetObjectDescription (
return cstr_len > 0;
}
+lldb::ModuleSP
+AppleObjCRuntime::GetObjCModule ()
+{
+ ModuleSP module_sp (m_objc_module_wp.lock());
+ if (module_sp)
+ return module_sp;
+
+ Process *process = GetProcess();
+ if (process)
+ {
+ const ModuleList& modules = process->GetTarget().GetImages();
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ module_sp = modules.GetModuleAtIndex(idx);
+ if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp))
+ {
+ m_objc_module_wp = module_sp;
+ return module_sp;
+ }
+ }
+ }
+ return ModuleSP();
+}
+
Address *
AppleObjCRuntime::GetPrintForDebuggerAddr()
{
if (!m_PrintForDebugger_addr.get())
{
- ModuleList &modules = m_process->GetTarget().GetImages();
+ const ModuleList &modules = m_process->GetTarget().GetImages();
SymbolContextList contexts;
SymbolContext context;
@@ -211,15 +239,17 @@ AppleObjCRuntime::GetDynamicTypeAndAddre
bool
AppleObjCRuntime::AppleIsModuleObjCLibrary (const ModuleSP &module_sp)
{
- const FileSpec &module_file_spec = module_sp->GetFileSpec();
- static ConstString ObjCName ("libobjc.A.dylib");
-
- if (module_file_spec)
+ if (module_sp)
{
- if (module_file_spec.GetFilename() == ObjCName)
- return true;
+ const FileSpec &module_file_spec = module_sp->GetFileSpec();
+ static ConstString ObjCName ("libobjc.A.dylib");
+
+ if (module_file_spec)
+ {
+ if (module_file_spec.GetFilename() == ObjCName)
+ return true;
+ }
}
-
return false;
}
@@ -263,7 +293,7 @@ AppleObjCRuntime::GetObjCVersion (Proces
return eObjC_VersionUnknown;
Target &target = process->GetTarget();
- ModuleList &target_modules = target.GetImages();
+ const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
size_t num_images = target_modules.GetSize();
@@ -305,11 +335,15 @@ AppleObjCRuntime::SetExceptionBreakpoint
const bool is_internal = true;
if (!m_objc_exception_bp_sp)
+ {
m_objc_exception_bp_sp = LanguageRuntime::CreateExceptionBreakpoint (m_process->GetTarget(),
GetLanguageType(),
catch_bp,
throw_bp,
is_internal);
+ if (m_objc_exception_bp_sp)
+ m_objc_exception_bp_sp->SetBreakpointKind("ObjC exception");
+ }
else
m_objc_exception_bp_sp->SetEnabled(true);
}
@@ -361,3 +395,21 @@ AppleObjCRuntime::CalculateHasNewLiteral
else
return false;
}
+
+lldb::SearchFilterSP
+AppleObjCRuntime::CreateExceptionSearchFilter ()
+{
+ Target &target = m_process->GetTarget();
+
+ if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
+ {
+ FileSpecList filter_modules;
+ filter_modules.Append(FileSpec("libobjc.A.dylib", false));
+ return target.GetSearchFilterForModuleList(&filter_modules);
+ }
+ else
+ {
+ return LanguageRuntime::CreateExceptionSearchFilter();
+ }
+}
+
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h Thu Jun 6 19:06:43 2013
@@ -63,29 +63,10 @@ public:
virtual lldb::ThreadPlanSP
GetStepThroughTrampolinePlan (Thread &thread, bool stop_others);
- virtual bool
- IsValidISA(ObjCISA isa)
- {
- return false;
- }
-
- virtual ObjCISA
- GetISA(ValueObject& valobj)
- {
- return 0;
- }
-
- virtual ConstString
- GetActualTypeName(ObjCISA isa)
- {
- return ConstString(NULL);
- }
-
- virtual ObjCISA
- GetParentClass(ObjCISA isa)
- {
- return 0;
- }
+ // Get the "libobjc.A.dylib" module from the current target if we can find
+ // it, also cache it once it is found to ensure quick lookups.
+ lldb::ModuleSP
+ GetObjCModule ();
//------------------------------------------------------------------
// Static Functions
@@ -115,20 +96,27 @@ public:
virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
+
+ virtual lldb::SearchFilterSP
+ CreateExceptionSearchFilter ();
+
protected:
Address *
GetPrintForDebuggerAddr();
- std::auto_ptr<Address> m_PrintForDebugger_addr;
+ std::unique_ptr<Address> m_PrintForDebugger_addr;
bool m_read_objc_library;
- std::auto_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
+ std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
lldb::BreakpointSP m_objc_exception_bp_sp;
+ lldb::ModuleWP m_objc_module_wp;
- AppleObjCRuntime(Process *process) :
+ AppleObjCRuntime(Process *process) :
lldb_private::ObjCLanguageRuntime(process),
m_read_objc_library (false),
- m_objc_trampoline_handler_ap(NULL)
- { } // Call CreateInstance instead.
+ m_objc_trampoline_handler_ap ()
+ {
+ // Call CreateInstance instead.
+ }
};
} // namespace lldb_private
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp Thu Jun 6 19:06:43 2013
@@ -9,6 +9,7 @@
#include "AppleObjCRuntimeV1.h"
#include "AppleObjCTrampolineHandler.h"
+#include "AppleObjCTypeVendor.h"
#include "llvm/Support/MachO.h"
#include "clang/AST/Type.h"
@@ -24,6 +25,7 @@
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -35,17 +37,33 @@
using namespace lldb;
using namespace lldb_private;
-static const char *pluginName = "AppleObjCRuntimeV1";
-static const char *pluginDesc = "Apple Objective C Language Runtime - Version 1";
-static const char *pluginShort = "language.apple.objc.v1";
+AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process) :
+ AppleObjCRuntime (process),
+ m_hash_signature (),
+ m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS)
+{
+}
+// for V1 runtime we just try to return a class name as that is the minimum level of support
+// required for the data formatters to work
bool
-AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value,
+AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
Address &address)
{
- return false;
+ class_type_or_name.Clear();
+ if (CouldHaveDynamicValue(in_value))
+ {
+ auto class_descriptor(GetClassDescriptor(in_value));
+ if (class_descriptor && class_descriptor->IsValid() && class_descriptor->GetClassName())
+ {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+ class_type_or_name.SetName(class_descriptor->GetClassName());
+ }
+ }
+ return class_type_or_name.IsEmpty() == false;
}
//------------------------------------------------------------------
@@ -69,11 +87,12 @@ AppleObjCRuntimeV1::CreateInstance (Proc
return NULL;
}
+
void
AppleObjCRuntimeV1::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Apple Objective C Language Runtime - Version 1",
CreateInstance);
}
@@ -83,19 +102,20 @@ AppleObjCRuntimeV1::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+AppleObjCRuntimeV1::GetPluginNameStatic()
+{
+ static ConstString g_name("apple-objc-v1");
+ return g_name;
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+ConstString
AppleObjCRuntimeV1::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-AppleObjCRuntimeV1::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
@@ -126,7 +146,7 @@ struct BufStruct {
ClangUtilityFunction *
AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
{
- std::auto_ptr<BufStruct> buf(new BufStruct);
+ std::unique_ptr<BufStruct> buf(new BufStruct);
assert(snprintf(&buf->contents[0], sizeof(buf->contents),
"struct __objc_class \n"
@@ -152,3 +172,311 @@ AppleObjCRuntimeV1::CreateObjectChecker(
return new ClangUtilityFunction(buf->contents, name);
}
+
+// this code relies on the assumption that an Objective-C object always starts
+// with an ISA at offset 0.
+//ObjCLanguageRuntime::ObjCISA
+//AppleObjCRuntimeV1::GetISA(ValueObject& valobj)
+//{
+//// if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
+//// return 0;
+//
+// // if we get an invalid VO (which might still happen when playing around
+// // with pointers returned by the expression parser, don't consider this
+// // a valid ObjC object)
+// if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
+// return 0;
+//
+// addr_t isa_pointer = valobj.GetPointerValue();
+//
+// ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+//
+// Process *process = exe_ctx.GetProcessPtr();
+// if (process)
+// {
+// uint8_t pointer_size = process->GetAddressByteSize();
+//
+// Error error;
+// return process->ReadUnsignedIntegerFromMemory (isa_pointer,
+// pointer_size,
+// 0,
+// error);
+// }
+// return 0;
+//}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
+{
+ Initialize (isa_pointer.GetValueAsUnsigned(0),
+ isa_pointer.GetProcessSP());
+}
+
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+ Initialize (isa, process_sp);
+}
+
+void
+AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
+{
+ if (!isa || !process_sp)
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_valid = true;
+
+ Error error;
+
+ m_isa = process_sp->ReadPointerFromMemory(isa, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ if (!IsPointerValid(m_isa,ptr_size))
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ if (!IsPointerValid(m_parent_isa,ptr_size,true))
+ {
+ m_valid = false;
+ return;
+ }
+
+ lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+
+ size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ if (count)
+ m_name = ConstString((char*)buffer_sp->GetBytes());
+ else
+ m_name = ConstString();
+
+ m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
+
+ if (error.Fail())
+ {
+ m_valid = false;
+ return;
+ }
+
+ m_process_wp = lldb::ProcessWP(process_sp);
+}
+
+AppleObjCRuntime::ClassDescriptorSP
+AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
+{
+ if (!m_valid)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ ProcessSP process_sp = m_process_wp.lock();
+ if (!process_sp)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
+}
+
+bool
+AppleObjCRuntimeV1::ClassDescriptorV1::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
+{
+ return false;
+}
+
+lldb::addr_t
+AppleObjCRuntimeV1::GetISAHashTablePointer ()
+{
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
+ {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData);
+ if (symbol)
+ {
+ Process *process = GetProcess();
+ if (process)
+ {
+
+ lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
+
+ if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
+ {
+ Error error;
+ lldb::addr_t objc_debug_class_hash_ptr = process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+ if (objc_debug_class_hash_ptr != 0 &&
+ objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
+ {
+ m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
+ }
+ }
+ }
+ }
+ }
+ return m_isa_hash_table_ptr;
+}
+
+void
+AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
+{
+ // TODO: implement HashTableSignature...
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ // Update the process stop ID that indicates the last time we updated the
+ // map, wether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ProcessSP process_sp = process->shared_from_this();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return;
+
+ uint32_t isa_count = 0;
+
+ lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
+ if (hash_table_ptr != LLDB_INVALID_ADDRESS)
+ {
+ // Read the NXHashTable struct:
+ //
+ // typedef struct {
+ // const NXHashTablePrototype *prototype;
+ // unsigned count;
+ // unsigned nbBuckets;
+ // void *buckets;
+ // const void *info;
+ // } NXHashTable;
+
+ Error error;
+ DataBufferHeap buffer(1024, 0);
+ if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
+ {
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
+ lldb::offset_t offset = addr_size; // Skip prototype
+ const uint32_t count = data.GetU32(&offset);
+ const uint32_t num_buckets = data.GetU32(&offset);
+ const addr_t buckets_ptr = data.GetPointer(&offset);
+ if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
+ {
+ m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);
+
+ const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+ buffer.SetByteSize(data_size);
+
+ if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
+ {
+ data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
+ offset = 0;
+ for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
+ {
+ const uint32_t bucket_isa_count = data.GetU32 (&offset);
+ const lldb::addr_t bucket_data = data.GetU32 (&offset);
+
+
+ if (bucket_isa_count == 0)
+ continue;
+
+ isa_count += bucket_isa_count;
+
+ ObjCISA isa;
+ if (bucket_isa_count == 1)
+ {
+ // When we only have one entry in the bucket, the bucket data is the "isa"
+ isa = bucket_data;
+ if (isa)
+ {
+ if (!ISAIsCached(isa))
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ AddClass (isa, descriptor_sp);
+ }
+ }
+ }
+ else
+ {
+ // When we have more than one entry in the bucket, the bucket data is a pointer
+ // to an array of "isa" values
+ addr_t isa_addr = bucket_data;
+ for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
+ {
+ isa = m_process->ReadPointerFromMemory(isa_addr, error);
+
+ if (isa && isa != LLDB_INVALID_ADDRESS)
+ {
+ if (!ISAIsCached(isa))
+ {
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
+
+ AddClass (isa, descriptor_sp);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
+}
+
+TypeVendor *
+AppleObjCRuntimeV1::GetTypeVendor()
+{
+ if (!m_type_vendor_ap.get())
+ m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
+
+ return m_type_vendor_ap.get();
+}
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h Thu Jun 6 19:06:43 2013
@@ -24,6 +24,72 @@ class AppleObjCRuntimeV1 :
public AppleObjCRuntime
{
public:
+
+ class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor
+ {
+ public:
+ ClassDescriptorV1 (ValueObject &isa_pointer);
+ ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp);
+
+ virtual ConstString
+ GetClassName ()
+ {
+ return m_name;
+ }
+
+ virtual ClassDescriptorSP
+ GetSuperclass ();
+
+ virtual bool
+ IsValid ()
+ {
+ return m_valid;
+ }
+
+ // v1 does not support tagged pointers
+ virtual bool
+ GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
+ {
+ return false;
+ }
+
+ virtual uint64_t
+ GetInstanceSize ()
+ {
+ return m_instance_size;
+ }
+
+ virtual ObjCISA
+ GetISA ()
+ {
+ return m_isa;
+ }
+
+ virtual bool
+ Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func);
+
+ virtual
+ ~ClassDescriptorV1 ()
+ {}
+
+ protected:
+ void
+ Initialize (ObjCISA isa, lldb::ProcessSP process_sp);
+
+ private:
+ ConstString m_name;
+ ObjCISA m_isa;
+ ObjCISA m_parent_isa;
+ bool m_valid;
+ lldb::ProcessWP m_process_wp;
+ uint64_t m_instance_size;
+ };
+
virtual ~AppleObjCRuntimeV1() { }
// These are generic runtime functions:
@@ -48,15 +114,15 @@ public:
static lldb_private::LanguageRuntime *
CreateInstance (Process *process, lldb::LanguageType language);
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -66,38 +132,62 @@ public:
return eAppleObjC_V1;
}
- virtual bool
- IsValidISA(ObjCISA isa)
- {
- return false;
- }
-
- virtual ObjCISA
- GetISA(ValueObject& valobj)
- {
- return 0;
- }
+ virtual void
+ UpdateISAToDescriptorMapIfNeeded();
- virtual ConstString
- GetActualTypeName(ObjCISA isa)
- {
- return ConstString(NULL);
- }
-
- virtual ObjCISA
- GetParentClass(ObjCISA isa)
- {
- return 0;
- }
+ virtual TypeVendor *
+ GetTypeVendor();
protected:
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
-
+
+
+ class HashTableSignature
+ {
+ public:
+ HashTableSignature () :
+ m_count (0),
+ m_num_buckets (0),
+ m_buckets_ptr (LLDB_INVALID_ADDRESS)
+ {
+ }
+
+ bool
+ NeedsUpdate (uint32_t count,
+ uint32_t num_buckets,
+ lldb::addr_t buckets_ptr)
+ {
+ return m_count != count ||
+ m_num_buckets != num_buckets ||
+ m_buckets_ptr != buckets_ptr ;
+ }
+
+ void
+ UpdateSignature (uint32_t count,
+ uint32_t num_buckets,
+ lldb::addr_t buckets_ptr)
+ {
+ m_count = count;
+ m_num_buckets = num_buckets;
+ m_buckets_ptr = buckets_ptr;
+ }
+
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
+
+
+ lldb::addr_t
+ GetISAHashTablePointer ();
+
+ HashTableSignature m_hash_signature;
+ lldb::addr_t m_isa_hash_table_ptr;
+ std::unique_ptr<TypeVendor> m_type_vendor_ap;
private:
- AppleObjCRuntimeV1(Process *process) :
- lldb_private::AppleObjCRuntime (process)
- { } // Call CreateInstance instead.
+ AppleObjCRuntimeV1(Process *process);
};
} // namespace lldb_private
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp Thu Jun 6 19:06:43 2013
@@ -7,17 +7,16 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/lldb-python.h"
#include <string>
#include <vector>
-#include <memory>
#include <stdint.h>
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
@@ -25,11 +24,17 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -37,212 +42,324 @@
#include "lldb/Target/Thread.h"
#include "AppleObjCRuntimeV2.h"
-#include "AppleObjCSymbolVendor.h"
+#include "AppleObjCTypeVendor.h"
#include "AppleObjCTrampolineHandler.h"
#include <vector>
using namespace lldb;
using namespace lldb_private;
-
-static const char *pluginName = "AppleObjCRuntimeV2";
-static const char *pluginDesc = "Apple Objective C Language Runtime - Version 2";
-static const char *pluginShort = "language.apple.objc.v2";
-
-
-const char *AppleObjCRuntimeV2::g_find_class_name_function_name = "__lldb_apple_objc_v2_find_class_name";
-const char *AppleObjCRuntimeV2::g_find_class_name_function_body = " \n\
-extern \"C\" \n\
-{ \n\
- extern void *gdb_class_getClass (void *objc_class); \n\
- extern void *class_getName(void *objc_class); \n\
- extern int printf(const char *format, ...); \n\
- extern unsigned char class_isMetaClass (void *objc_class); \n\
-} \n\
- \n\
-struct __lldb_objc_object { \n\
- void *isa; \n\
-}; \n\
- \n\
-extern \"C\" void *__lldb_apple_objc_v2_find_class_name ( \n\
- __lldb_objc_object *object_ptr, \n\
- int debug) \n\
-{ \n\
- void *name = 0; \n\
- if (debug) \n\
- printf (\"\\n*** Called in v2_find_class_name with object: 0x%p\\n\", object_ptr); \n\
- // Call gdb_class_getClass so we can tell if the class is good. \n\
- void *objc_class = gdb_class_getClass (object_ptr->isa); \n\
- if (objc_class) \n\
- { \n\
- void *actual_class = (void *) [(id) object_ptr class]; \n\
- if (actual_class != 0) \n\
- { \n\
- if (class_isMetaClass(actual_class) == 1) \n\
- { \n\
- if (debug) \n\
- printf (\"\\n*** Found metaclass.\\n\"); \n\
- } \n\
- else \n\
- { \n\
- name = class_getName((void *) actual_class); \n\
- } \n\
- } \n\
- if (debug) \n\
- printf (\"\\n*** Found name: %s\\n\", name ? name : \"<NOT FOUND>\"); \n\
- } \n\
- else if (debug) \n\
- printf (\"\\n*** gdb_class_getClass returned NULL\\n\"); \n\
- return name; \n\
-} \n\
-";
+// 2 second timeout when running utility functions
+#define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
-AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
- const ModuleSP &objc_module_sp) :
- AppleObjCRuntime (process),
- m_get_class_name_args(LLDB_INVALID_ADDRESS),
- m_get_class_name_args_mutex(Mutex::eMutexTypeNormal),
- m_isa_to_name_cache(),
- m_isa_to_parent_cache()
+static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+// need to revert to the code above...
+static const char *g_get_dynamic_class_info_body = R"(
+
+extern "C"
{
- static const ConstString g_gdb_object_getClass("gdb_object_getClass");
- m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+ size_t strlen(const char *);
+ char *strncpy (char * s1, const char * s2, size_t n);
+ int printf(const char * format, ...);
}
+//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+typedef struct _NXMapTable {
+ void *prototype;
+ unsigned num_classes;
+ unsigned num_buckets_minus_one;
+ void *buckets;
+} NXMapTable;
-bool
-AppleObjCRuntimeV2::RunFunctionToFindClassName(addr_t object_addr, Thread *thread, char *name_dst, size_t max_name_len)
+#define NX_MAPNOTAKEY ((void *)(-1))
+
+typedef struct BucketInfo
{
- // Since we are going to run code we have to make sure only one thread at a time gets to try this.
- Mutex::Locker (m_get_class_name_args_mutex);
-
- StreamString errors;
-
- LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); // FIXME - a more appropriate log channel?
-
- int32_t debug;
- if (log && log->GetVerbose())
- debug = 1;
- else
- debug = 0;
+ const char *name_ptr;
+ Class isa;
+} BucketInfo;
- ValueList dispatch_values;
-
- Value void_ptr_value;
- ClangASTContext *clang_ast_context = m_process->GetTarget().GetScratchClangASTContext();
-
- clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
- void_ptr_value.SetValueType (Value::eValueTypeScalar);
- void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
- void_ptr_value.GetScalar() = object_addr;
-
- dispatch_values.PushValue (void_ptr_value);
-
- Value int_value;
- clang_type_t clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32);
- int_value.SetValueType (Value::eValueTypeScalar);
- int_value.SetContext (Value::eContextTypeClangType, clang_int_type);
- int_value.GetScalar() = debug;
-
- dispatch_values.PushValue (int_value);
-
- ExecutionContext exe_ctx;
- thread->CalculateExecutionContext(exe_ctx);
-
- Address find_class_name_address;
-
- if (!m_get_class_name_code.get())
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size)
+{
+ DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
+ const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
+ if (grc)
{
- m_get_class_name_code.reset (new ClangUtilityFunction (g_find_class_name_function_body,
- g_find_class_name_function_name));
-
- if (!m_get_class_name_code->Install(errors, exe_ctx))
+ const unsigned num_classes = grc->num_classes;
+ if (class_infos_ptr)
{
- if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
- m_get_class_name_code.reset();
- return false;
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+ BucketInfo *buckets = (BucketInfo *)grc->buckets;
+
+ uint32_t idx = 0;
+ for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
+ {
+ if (buckets[i].name_ptr != NX_MAPNOTAKEY)
+ {
+ if (idx < max_class_infos)
+ {
+ const char *s = buckets[i].name_ptr;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ class_infos[idx].isa = buckets[i].isa;
+ }
+ ++idx;
+ }
+ }
+ if (idx < max_class_infos)
+ {
+ class_infos[idx].isa = NULL;
+ class_infos[idx].hash = 0;
+ }
}
- find_class_name_address.Clear();
- find_class_name_address.SetOffset(m_get_class_name_code->StartAddress());
+ return num_classes;
}
- else
+ return 0;
+}
+
+)";
+
+static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+// need to revert to the code above...
+static const char *g_get_shared_cache_class_info_body = R"(
+
+extern "C"
+{
+ const char *class_getName(void *objc_class);
+ size_t strlen(const char *);
+ char *strncpy (char * s1, const char * s2, size_t n);
+ int printf(const char * format, ...);
+}
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
+#ifdef ENABLE_DEBUG_PRINTF
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+
+struct objc_classheader_t {
+ int32_t clsOffset;
+ int32_t hiOffset;
+};
+
+struct objc_clsopt_t {
+ uint32_t capacity;
+ uint32_t occupied;
+ uint32_t shift;
+ uint32_t mask;
+ uint32_t zero;
+ uint32_t unused;
+ uint64_t salt;
+ uint32_t scramble[256];
+ uint8_t tab[0]; // tab[mask+1]
+ // uint8_t checkbytes[capacity];
+ // int32_t offset[capacity];
+ // objc_classheader_t clsOffsets[capacity];
+ // uint32_t duplicateCount;
+ // objc_classheader_t duplicateOffsets[duplicateCount];
+};
+
+struct objc_opt_t {
+ uint32_t version;
+ int32_t selopt_offset;
+ int32_t headeropt_offset;
+ int32_t clsopt_offset;
+};
+
+struct ClassInfo
+{
+ Class isa;
+ uint32_t hash;
+} __attribute__((__packed__));
+
+uint32_t
+__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
+ void *class_infos_ptr,
+ uint32_t class_infos_byte_size)
+{
+ uint32_t idx = 0;
+ DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
+ DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
+ DEBUG_PRINTF ("class_infos_byte_size = %u (%zu class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
+ if (objc_opt_ro_ptr)
{
- find_class_name_address.Clear();
- find_class_name_address.SetOffset(m_get_class_name_code->StartAddress());
+ const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
+ DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
+ DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
+ DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
+ DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
+ if (objc_opt->version == 12)
+ {
+ const objc_clsopt_t* clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
+ const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
+ int32_t zeroOffset = 16;
+ const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
+ const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
+ const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
+ DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
+ DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+ for (uint32_t i=0; i<clsopt->capacity; ++i)
+ {
+ const int32_t clsOffset = classOffsets[i].clsOffset;
+ if (clsOffset & 1)
+ continue; // duplicate
+ else if (clsOffset == zeroOffset)
+ continue; // zero offset
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
+ const char *name = class_getName (class_infos[idx].isa);
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+ // Hash the class name so we don't have to read it
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ }
+ ++idx;
+ }
+
+ const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
+ const uint32_t duplicate_count = *duplicate_count_ptr;
+ const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
+ DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
+ DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
+ for (uint32_t i=0; i<duplicate_count; ++i)
+ {
+ const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
+ if (clsOffset & 1)
+ continue; // duplicate
+ else if (clsOffset == zeroOffset)
+ continue; // zero offset
+
+ if (class_infos && idx < max_class_infos)
+ {
+ class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
+ const char *name = class_getName (class_infos[idx].isa);
+ DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
+ // Hash the class name so we don't have to read it
+ const char *s = name;
+ uint32_t h = 5381;
+ for (unsigned char c = *s; c; c = *++s)
+ h = ((h << 5) + h) + c;
+ class_infos[idx].hash = h;
+ }
+ ++idx;
+ }
+ }
+ DEBUG_PRINTF ("%u class_infos\n", idx);
+ DEBUG_PRINTF ("done\n");
}
+ return idx;
+}
- // Next make the runner function for our implementation utility function.
- if (!m_get_class_name_function.get())
+
+)";
+
+static uint64_t
+ExtractRuntimeGlobalSymbol (Process* process,
+ ConstString name,
+ const ModuleSP &module_sp,
+ Error& error,
+ bool read_value = true,
+ uint8_t byte_size = 0,
+ uint64_t default_value = LLDB_INVALID_ADDRESS,
+ SymbolType sym_type = lldb::eSymbolTypeData)
+{
+ if (!process)
{
- m_get_class_name_function.reset(new ClangFunction (*m_process,
- clang_ast_context,
- clang_void_ptr_type,
- find_class_name_address,
- dispatch_values));
-
- errors.Clear();
- unsigned num_errors = m_get_class_name_function->CompileFunction(errors);
- if (num_errors)
+ error.SetErrorString("no process");
+ return default_value;
+ }
+ if (!module_sp)
+ {
+ error.SetErrorString("no module");
+ return default_value;
+ }
+ if (!byte_size)
+ byte_size = process->GetAddressByteSize();
+ const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
+ if (symbol)
+ {
+ lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
{
- if (log)
- log->Printf ("Error compiling function: \"%s\".", errors.GetData());
- return false;
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
+ else
+ return symbol_load_addr;
}
-
- errors.Clear();
- if (!m_get_class_name_function->WriteFunctionWrapper(exe_ctx, errors))
+ else
{
- if (log)
- log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
- return false;
+ error.SetErrorString("symbol address invalid");
+ return default_value;
}
}
-
- if (m_get_class_name_code.get() == NULL || m_get_class_name_function.get() == NULL)
- return false;
-
- // Finally, write down the arguments, and call the function. Note that we will re-use the same space in the target
- // for the args. We're locking this to ensure that only one thread at a time gets to call this function, so we don't
- // have to worry about overwriting the arguments.
-
- if (!m_get_class_name_function->WriteFunctionArguments (exe_ctx, m_get_class_name_args, find_class_name_address, dispatch_values, errors))
- return false;
-
- bool stop_others = true;
- bool try_all_threads = true;
- bool unwind_on_error = true;
-
- ExecutionResults results = m_get_class_name_function->ExecuteFunction (exe_ctx,
- &m_get_class_name_args,
- errors,
- stop_others,
- 100000,
- try_all_threads,
- unwind_on_error,
- void_ptr_value);
-
- if (results != eExecutionCompleted)
+ else
{
- if (log)
- log->Printf("Error evaluating our find class name function: %d.\n", results);
- return false;
+ error.SetErrorString("no symbol");
+ return default_value;
}
-
- addr_t result_ptr = void_ptr_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
- Error error;
- size_t chars_read = m_process->ReadCStringFromMemory (result_ptr, name_dst, max_name_len, error);
-
- // If we exhausted our buffer before finding a NULL we're probably off in the weeds somewhere...
- if (error.Fail() || chars_read == max_name_len)
- return false;
- else
- return true;
-
+
+}
+
+AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
+ const ModuleSP &objc_module_sp) :
+ AppleObjCRuntime (process),
+ m_get_class_info_function(),
+ m_get_class_info_code(),
+ m_get_class_info_args (LLDB_INVALID_ADDRESS),
+ m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
+ m_get_shared_cache_class_info_function(),
+ m_get_shared_cache_class_info_code(),
+ m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
+ m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
+ m_type_vendor_ap (),
+ m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
+ m_hash_signature (),
+ m_has_object_getClass (false),
+ m_loaded_objc_opt (false),
+ m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
+ m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
+{
+ static const ConstString g_gdb_object_getClass("gdb_object_getClass");
+ m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+}
+
+AppleObjCRuntimeV2::~AppleObjCRuntimeV2()
+{
}
bool
-AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
+AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
Address &address)
@@ -250,159 +367,36 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAdd
// The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
assert (in_value.GetProcessSP().get() == m_process);
assert (m_process != NULL);
+
+ class_type_or_name.Clear();
// Make sure we can have a dynamic value before starting...
if (CouldHaveDynamicValue (in_value))
{
// First job, pull out the address at 0 offset from the object That will be the ISA pointer.
- Error error;
- const addr_t object_ptr = in_value.GetPointerValue();
- const addr_t isa_addr = m_process->ReadPointerFromMemory (object_ptr, error);
-
- if (error.Fail())
- return false;
-
- address.SetRawAddress(object_ptr);
-
- // First check the cache...
- SymbolContext sc;
- class_type_or_name = LookupInClassNameCache (isa_addr);
-
- if (!class_type_or_name.IsEmpty())
+ ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
+ if (objc_class_sp)
{
- if (class_type_or_name.GetTypeSP())
- return true;
- else
- return false;
- }
-
- // We don't have the object cached, so make sure the class
- // address is readable, otherwise this is not a good object:
- m_process->ReadPointerFromMemory (isa_addr, error);
-
- if (error.Fail())
- return false;
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
- const char *class_name = NULL;
- Address isa_address;
- Target &target = m_process->GetTarget();
- target.GetSectionLoadList().ResolveLoadAddress (isa_addr, isa_address);
-
- if (isa_address.IsValid())
- {
- // If the ISA pointer points to one of the sections in the binary, then see if we can
- // get the class name from the symbols.
-
- SectionSP section_sp (isa_address.GetSection());
-
- if (section_sp)
- {
- // If this points to a section that we know about, then this is
- // some static class or nothing. See if it is in the right section
- // and if its name is the right form.
- ConstString section_name = section_sp->GetName();
- static ConstString g_objc_class_section_name ("__objc_data");
- if (section_name == g_objc_class_section_name)
- {
- isa_address.CalculateSymbolContext(&sc);
- if (sc.symbol)
- {
- if (sc.symbol->GetType() == eSymbolTypeObjCClass)
- class_name = sc.symbol->GetName().GetCString();
- else if (sc.symbol->GetType() == eSymbolTypeObjCMetaClass)
- {
- // FIXME: Meta-classes can't have dynamic types...
- return false;
- }
- }
- }
- }
- }
-
- char class_buffer[1024];
- if (class_name == NULL && use_dynamic == eDynamicCanRunTarget)
- {
- // If the class address didn't point into the binary, or
- // it points into the right section but there wasn't a symbol
- // there, try to look it up by calling the class method in the target.
-
- ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
-
- Thread *thread_to_use = exe_ctx.GetThreadPtr();
-
- if (thread_to_use == NULL)
- thread_to_use = m_process->GetThreadList().GetSelectedThread().get();
-
- if (thread_to_use == NULL)
- return false;
-
- if (!RunFunctionToFindClassName (object_ptr, thread_to_use, class_buffer, 1024))
- return false;
-
- class_name = class_buffer;
-
- }
-
- if (class_name && class_name[0])
- {
- class_type_or_name.SetName (class_name);
-
- TypeList class_types;
- SymbolContext sc;
- const bool exact_match = true;
- uint32_t num_matches = target.GetImages().FindTypes (sc,
- class_type_or_name.GetName(),
- exact_match,
- UINT32_MAX,
- class_types);
- if (num_matches == 1)
- {
- class_type_or_name.SetTypeSP (class_types.GetTypeAtIndex(0));
- return true;
- }
+ ConstString class_name (objc_class_sp->GetClassName());
+ class_type_or_name.SetName(class_name);
+ TypeSP type_sp (objc_class_sp->GetType());
+ if (type_sp)
+ class_type_or_name.SetTypeSP (type_sp);
else
{
- for (size_t i = 0; i < num_matches; i++)
+ type_sp = LookupInCompleteClassCache (class_name);
+ if (type_sp)
{
- TypeSP this_type(class_types.GetTypeAtIndex(i));
- if (this_type)
- {
- // Only consider "real" ObjC classes. For now this means avoiding
- // the Type objects that are made up from the OBJC_CLASS_$_<NAME> symbols.
- // we don't want to use them since they are empty and useless.
- if (this_type->IsRealObjCClass())
- {
- // There can only be one type with a given name,
- // so we've just found duplicate definitions, and this
- // one will do as well as any other.
- // We don't consider something to have a dynamic type if
- // it is the same as the static type. So compare against
- // the value we were handed:
-
- clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
- clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
- if (in_ast_ctx != this_ast_ctx
- || !ClangASTContext::AreTypesSame (in_ast_ctx,
- in_value.GetClangType(),
- this_type->GetClangFullType()))
- {
- class_type_or_name.SetTypeSP (this_type);
- }
- break;
- }
- }
+ objc_class_sp->SetType (type_sp);
+ class_type_or_name.SetTypeSP (type_sp);
}
}
-
- AddToClassNameCache (isa_addr, class_type_or_name);
- if (class_type_or_name.GetTypeSP())
- return true;
- else
- return false;
}
- }
-
- return false;
+ }
+ return class_type_or_name.IsEmpty() == false;
}
//------------------------------------------------------------------
@@ -429,8 +423,8 @@ AppleObjCRuntimeV2::CreateInstance (Proc
void
AppleObjCRuntimeV2::Initialize()
{
- PluginManager::RegisterPlugin (pluginName,
- pluginDesc,
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Apple Objective C Language Runtime - Version 2",
CreateInstance);
}
@@ -440,19 +434,21 @@ AppleObjCRuntimeV2::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
+lldb_private::ConstString
+AppleObjCRuntimeV2::GetPluginNameStatic()
+{
+ static ConstString g_name("apple-objc-v2");
+ return g_name;
+}
+
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-const char *
+lldb_private::ConstString
AppleObjCRuntimeV2::GetPluginName()
{
- return pluginName;
-}
-
-const char *
-AppleObjCRuntimeV2::GetShortPluginName()
-{
- return pluginShort;
+ return GetPluginNameStatic();
}
uint32_t
@@ -574,207 +570,2083 @@ AppleObjCRuntimeV2::GetByteOffsetForIvar
return ivar_offset;
}
-// tagged pointers are marked by having their least-significant bit
-// set. this makes them "invalid" as pointers because they violate
-// the alignment requirements. of course, this detection algorithm
-// is not accurate (it might become better by incorporating further
-// knowledge about the internals of tagged pointers)
+
+// tagged pointers are special not-a-real-pointer values that contain both type and value information
+// this routine attempts to check with as little computational effort as possible whether something
+// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
bool
AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
{
- return (ptr & 0x01);
+ if (!m_tagged_pointer_vendor_ap)
+ return false;
+ return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
}
-
-// this code relies on the assumption that an Objective-C object always starts
-// with an ISA at offset 0. an ISA is effectively a pointer to an instance of
-// struct class_t in the ObjCv2 runtime
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV2::GetISA(ValueObject& valobj)
+class RemoteNXMapTable
{
- if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC)
- return 0;
-
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
- if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid)
- return 0;
+public:
- addr_t isa_pointer = valobj.GetPointerValue();
+ RemoteNXMapTable () :
+ m_count (0),
+ m_num_buckets_minus_one (0),
+ m_buckets_ptr (LLDB_INVALID_ADDRESS),
+ m_process (NULL),
+ m_end_iterator (*this, -1),
+ m_load_addr (LLDB_INVALID_ADDRESS),
+ m_map_pair_size (0),
+ m_invalid_key (0)
+ {
+ }
- // tagged pointer
- if (IsTaggedPointer(isa_pointer))
- return g_objc_Tagged_ISA;
-
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
+ void
+ Dump ()
{
- uint8_t pointer_size = process->GetAddressByteSize();
+ printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
+ printf ("RemoteNXMapTable.m_count = %u\n", m_count);
+ printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
+ printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
+ }
- Error error;
- return process->ReadUnsignedIntegerFromMemory (isa_pointer,
- pointer_size,
- 0,
- error);
+ bool
+ ParseHeader (Process* process, lldb::addr_t load_addr)
+ {
+ m_process = process;
+ m_load_addr = load_addr;
+ m_map_pair_size = m_process->GetAddressByteSize() * 2;
+ m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
+ Error err;
+
+ // This currently holds true for all platforms we support, but we might
+ // need to change this to use get the actualy byte size of "unsigned"
+ // from the target AST...
+ const uint32_t unsigned_byte_size = sizeof(uint32_t);
+ // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
+
+ bool success = true;
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ success = false;
+ else
+ {
+ lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
+
+ // unsigned count;
+ m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
+ if (m_count)
+ {
+ cursor += unsigned_byte_size;
+
+ // unsigned nbBucketsMinusOne;
+ m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
+ cursor += unsigned_byte_size;
+
+ // void *buckets;
+ m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
+
+ success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
+ }
+ }
+
+ if (!success)
+ {
+ m_count = 0;
+ m_num_buckets_minus_one = 0;
+ m_buckets_ptr = LLDB_INVALID_ADDRESS;
+ }
+ return success;
}
- return 0;
-}
+
+ // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
+ typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
-// TODO: should we have a transparent_kvo parameter here to say if we
-// want to replace the KVO swizzled class with the actual user-level type?
-ConstString
-AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
-{
- static const ConstString g_unknown ("unknown");
+ friend class const_iterator;
+ class const_iterator
+ {
+ public:
+ const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
+ {
+ AdvanceToValidIndex();
+ }
+
+ const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
+ {
+ // AdvanceToValidIndex() has been called by rhs already.
+ }
+
+ const_iterator &operator=(const const_iterator &rhs)
+ {
+ // AdvanceToValidIndex() has been called by rhs already.
+ assert (&m_parent == &rhs.m_parent);
+ m_index = rhs.m_index;
+ return *this;
+ }
+
+ bool operator==(const const_iterator &rhs) const
+ {
+ if (&m_parent != &rhs.m_parent)
+ return false;
+ if (m_index != rhs.m_index)
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const const_iterator &rhs) const
+ {
+ return !(operator==(rhs));
+ }
+
+ const_iterator &operator++()
+ {
+ AdvanceToValidIndex();
+ return *this;
+ }
+
+ const element operator*() const
+ {
+ if (m_index == -1)
+ {
+ // TODO find a way to make this an error, but not an assert
+ return element();
+ }
+
+ lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ size_t map_pair_size = m_parent.m_map_pair_size;
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+
+ Error err;
+
+ lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+ if (!err.Success())
+ return element();
+ lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
+ if (!err.Success())
+ return element();
+
+ std::string key_string;
+
+ m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
+ if (!err.Success())
+ return element();
+
+ return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
+ }
+ private:
+ void AdvanceToValidIndex ()
+ {
+ if (m_index == -1)
+ return;
+
+ const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ const size_t map_pair_size = m_parent.m_map_pair_size;
+ const lldb::addr_t invalid_key = m_parent.m_invalid_key;
+ Error err;
- if (!IsValidISA(isa))
- return ConstString();
-
- if (isa == g_objc_Tagged_ISA)
+ while (m_index--)
+ {
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+ lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+
+ if (!err.Success())
+ {
+ m_index = -1;
+ return;
+ }
+
+ if (key != invalid_key)
+ return;
+ }
+ }
+ RemoteNXMapTable &m_parent;
+ int m_index;
+ };
+
+ const_iterator begin ()
{
- static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
- return g_objc_tagged_isa_name;
+ return const_iterator(*this, m_num_buckets_minus_one + 1);
}
- ISAToNameIterator found = m_isa_to_name_cache.find(isa);
- ISAToNameIterator end = m_isa_to_name_cache.end();
-
- if (found != end)
- return found->second;
+ const_iterator end ()
+ {
+ return m_end_iterator;
+ }
- uint8_t pointer_size = m_process->GetAddressByteSize();
- Error error;
+ uint32_t
+ GetCount () const
+ {
+ return m_count;
+ }
- /*
- struct class_t *isa;
- struct class_t *superclass;
- Cache cache;
- IMP *vtable;
---> class_rw_t data;
- */
-
- addr_t rw_pointer = isa + (4 * pointer_size);
- //printf("rw_pointer: %llx\n", rw_pointer);
- uint64_t data_pointer = m_process->ReadUnsignedIntegerFromMemory(rw_pointer,
- pointer_size,
- 0,
- error);
- if (error.Fail())
+ uint32_t
+ GetBucketCount () const
{
- return g_unknown;
-
+ return m_num_buckets_minus_one;
}
- /*
- uint32_t flags;
- uint32_t version;
-
---> const class_ro_t *ro;
- */
- data_pointer += 8;
- //printf("data_pointer: %llx\n", data_pointer);
- uint64_t ro_pointer = m_process->ReadUnsignedIntegerFromMemory(data_pointer,
- pointer_size,
- 0,
- error);
- if (error.Fail())
- return g_unknown;
+ lldb::addr_t
+ GetBucketDataPointer () const
+ {
+ return m_buckets_ptr;
+ }
- /*
- uint32_t flags;
- uint32_t instanceStart;
- uint32_t instanceSize;
- #ifdef __LP64__
- uint32_t reserved;
- #endif
-
- const uint8_t * ivarLayout;
-
---> const char * name;
- */
- ro_pointer += 12;
- if (pointer_size == 8)
- ro_pointer += 4;
- ro_pointer += pointer_size;
- //printf("ro_pointer: %llx\n", ro_pointer);
- uint64_t name_pointer = m_process->ReadUnsignedIntegerFromMemory(ro_pointer,
- pointer_size,
- 0,
- error);
- if (error.Fail())
- return g_unknown;
+ lldb::addr_t
+ GetTableLoadAddress() const
+ {
+ return m_load_addr;
+ }
+
+private:
+ // contents of _NXMapTable struct
+ uint32_t m_count;
+ uint32_t m_num_buckets_minus_one;
+ lldb::addr_t m_buckets_ptr;
+ lldb_private::Process *m_process;
+ const_iterator m_end_iterator;
+ lldb::addr_t m_load_addr;
+ size_t m_map_pair_size;
+ lldb::addr_t m_invalid_key;
+};
+
+
+
+AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
+ m_count (0),
+ m_num_buckets (0),
+ m_buckets_ptr (0)
+{
+}
+
+void
+AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
+{
+ m_count = hash_table.GetCount();
+ m_num_buckets = hash_table.GetBucketCount();
+ m_buckets_ptr = hash_table.GetBucketDataPointer();
+}
+
+bool
+AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
+{
+ if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
+ {
+ return false; // Failed to parse the header, no need to update anything
+ }
+
+ // Check with out current signature and return true if the count,
+ // number of buckets or the hash table address changes.
+ if (m_count == hash_table.GetCount() &&
+ m_num_buckets == hash_table.GetBucketCount() &&
+ m_buckets_ptr == hash_table.GetBucketDataPointer())
+ {
+ // Hash table hasn't changed
+ return false;
+ }
+ // Hash table data has changed, we need to update
+ return true;
+}
+
+class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+ friend class lldb_private::AppleObjCRuntimeV2;
+
+private:
+ // The constructor should only be invoked by the runtime as it builds its caches
+ // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
+ ClassDescriptorV2 (AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
+ m_runtime (runtime),
+ m_objc_class_ptr (isa),
+ m_name (name)
+ {
+ }
+
+public:
+ virtual ConstString
+ GetClassName ()
+ {
+ if (!m_name)
+ {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (process)
+ {
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return m_name;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return m_name;
+
+ m_name = ConstString(class_ro->m_name.c_str());
+ }
+ }
+ return m_name;
+ }
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetSuperclass ()
+ {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (!process)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ std::unique_ptr<objc_class_t> objc_class;
+
+ if (!Read_objc_class(process, objc_class))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
+ }
+
+ virtual bool
+ IsValid ()
+ {
+ return true; // any Objective-C v2 runtime class descriptor we vend is valid
+ }
+
+ // a custom descriptor is used for tagged pointers
+ virtual bool
+ GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
+ {
+ return false;
+ }
+
+ virtual uint64_t
+ GetInstanceSize ()
+ {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (process)
+ {
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return 0;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return 0;
+
+ return class_ro->m_instanceSize;
+ }
+
+ return 0;
+ }
+
+ virtual ObjCLanguageRuntime::ObjCISA
+ GetISA ()
+ {
+ return m_objc_class_ptr;
+ }
+
+ virtual bool
+ Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function <bool (const char *, const char *)> const &instance_method_func,
+ std::function <bool (const char *, const char *)> const &class_method_func,
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
+ {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return 0;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return 0;
+
+ static ConstString NSObject_name("NSObject");
+
+ if (m_name != NSObject_name && superclass_func)
+ superclass_func(objc_class->m_superclass);
+
+ if (instance_method_func)
+ {
+ std::unique_ptr<method_list_t> base_method_list;
+
+ base_method_list.reset(new method_list_t);
+ if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
+ return false;
+
+ if (base_method_list->m_entsize != method_t::GetSize(process))
+ return false;
+
+ std::unique_ptr<method_t> method;
+ method.reset(new method_t);
+
+ for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
+ {
+ method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
+
+ if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
+ break;
+ }
+ }
+
+ if (class_method_func)
+ {
+ ClassDescriptorV2 metaclass(m_runtime, objc_class->m_isa, NULL); // The metaclass is not in the cache
+
+ // We don't care about the metaclass's superclass, or its class methods. Its instance methods are
+ // our class methods.
+
+ metaclass.Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
+ class_method_func,
+ std::function <bool (const char *, const char *)> (nullptr),
+ std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
+ }
+
+ if (ivar_func)
+ {
+ ivar_list_t ivar_list;
+ if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
+ return false;
+
+ if (ivar_list.m_entsize != ivar_t::GetSize(process))
+ return false;
+
+ ivar_t ivar;
+
+ for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
+ {
+ ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
+
+ if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ virtual
+ ~ClassDescriptorV2 ()
+ {
+ }
+
+private:
+ static const uint32_t RW_REALIZED = (1 << 31);
+
+ struct objc_class_t {
+ ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
+ ObjCLanguageRuntime::ObjCISA m_superclass;
+ lldb::addr_t m_cache_ptr;
+ lldb::addr_t m_vtable_ptr;
+ lldb::addr_t m_data_ptr;
+ uint8_t m_flags;
+
+ objc_class_t () :
+ m_isa (0),
+ m_superclass (0),
+ m_cache_ptr (0),
+ m_vtable_ptr (0),
+ m_data_ptr (0),
+ m_flags (0)
+ {
+ }
+
+ void
+ Clear()
+ {
+ m_isa = 0;
+ m_superclass = 0;
+ m_cache_ptr = 0;
+ m_vtable_ptr = 0;
+ m_data_ptr = 0;
+ m_flags = 0;
+ }
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t objc_class_size = ptr_size // uintptr_t isa;
+ + ptr_size // Class superclass;
+ + ptr_size // void *cache;
+ + ptr_size // IMP *vtable;
+ + ptr_size; // uintptr_t data_NEVER_USE;
+
+ DataBufferHeap objc_class_buf (objc_class_size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
+ m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
+ m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
+ m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
+ lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
+
+ m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
+ m_data_ptr = data_NEVER_USE & ~(lldb::addr_t)3;
+
+ return true;
+ }
+ };
+
+ struct class_ro_t {
+ uint32_t m_flags;
+ uint32_t m_instanceStart;
+ uint32_t m_instanceSize;
+ uint32_t m_reserved;
+
+ lldb::addr_t m_ivarLayout_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_baseMethods_ptr;
+ lldb::addr_t m_baseProtocols_ptr;
+ lldb::addr_t m_ivars_ptr;
+
+ lldb::addr_t m_weakIvarLayout_ptr;
+ lldb::addr_t m_baseProperties_ptr;
+
+ std::string m_name;
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t instanceStart;
+ + sizeof(uint32_t) // uint32_t instanceSize;
+ + (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only
+ + ptr_size // const uint8_t *ivarLayout;
+ + ptr_size // const char *name;
+ + ptr_size // const method_list_t *baseMethods;
+ + ptr_size // const protocol_list_t *baseProtocols;
+ + ptr_size // const ivar_list_t *ivars;
+ + ptr_size // const uint8_t *weakIvarLayout;
+ + ptr_size; // const property_list_t *baseProperties;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_instanceStart = extractor.GetU32_unchecked(&cursor);
+ m_instanceSize = extractor.GetU32_unchecked(&cursor);
+ if (ptr_size == 8)
+ m_reserved = extractor.GetU32_unchecked(&cursor);
+ else
+ m_reserved = 0;
+ m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ DataBufferHeap name_buf(1024, '\0');
+
+ process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
+
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ m_name.assign((char*)name_buf.GetBytes());
+
+ return true;
+ }
+ };
+
+ struct class_rw_t {
+ uint32_t m_flags;
+ uint32_t m_version;
+
+ lldb::addr_t m_ro_ptr;
+ union {
+ lldb::addr_t m_method_list_ptr;
+ lldb::addr_t m_method_lists_ptr;
+ };
+ lldb::addr_t m_properties_ptr;
+ lldb::addr_t m_protocols_ptr;
+
+ ObjCLanguageRuntime::ObjCISA m_firstSubclass;
+ ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t version;
+ + ptr_size // const class_ro_t *ro;
+ + ptr_size // union { method_list_t **method_lists; method_list_t *method_list; };
+ + ptr_size // struct chained_property_list *properties;
+ + ptr_size // const protocol_list_t **protocols;
+ + ptr_size // Class firstSubclass;
+ + ptr_size; // Class nextSiblingClass;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_version = extractor.GetU32_unchecked(&cursor);
+ m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
+ m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
+
+ return true;
+ }
+ };
+
+ struct method_list_t
+ {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
+ }
+ };
+
+ struct method_t
+ {
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_types_ptr;
+ lldb::addr_t m_imp_ptr;
+
+ std::string m_name;
+ std::string m_types;
+
+ static size_t GetSize(Process *process)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // SEL name;
+ + ptr_size // const char *types;
+ + ptr_size; // IMP imp;
+ }
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_types_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ const size_t buffer_size = 1024;
+ size_t count;
+
+ DataBufferHeap string_buf(buffer_size, 0);
+
+ count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+ m_name.assign((char*)string_buf.GetBytes(), count);
+
+ count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+ m_types.assign((char*)string_buf.GetBytes(), count);
+
+ return true;
+ }
+ };
+
+ struct ivar_list_t
+ {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t size = sizeof(uint32_t) // uint32_t entsize;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor);
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
+ }
+ };
+
+ struct ivar_t
+ {
+ lldb::addr_t m_offset_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_type_ptr;
+ uint32_t m_alignment;
+ uint32_t m_size;
+
+ std::string m_name;
+ std::string m_type;
+
+ static size_t GetSize(Process *process)
+ {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // uintptr_t *offset;
+ + ptr_size // const char *name;
+ + ptr_size // const char *type;
+ + sizeof(uint32_t) // uint32_t alignment;
+ + sizeof(uint32_t); // uint32_t size;
+ }
+
+ bool Read(Process *process, lldb::addr_t addr)
+ {
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer (size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail())
+ {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_type_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_alignment = extractor.GetU32_unchecked(&cursor);
+ m_size = extractor.GetU32_unchecked(&cursor);
+
+ const size_t buffer_size = 1024;
+ size_t count;
+
+ DataBufferHeap string_buf(buffer_size, 0);
+
+ count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+ m_name.assign((char*)string_buf.GetBytes(), count);
+
+ count = process->ReadCStringFromMemory(m_type_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
+ m_type.assign((char*)string_buf.GetBytes(), count);
+
+ return true;
+ }
+ };
+
+ bool Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class)
+ {
+ objc_class.reset(new objc_class_t);
+
+ bool ret = objc_class->Read (process, m_objc_class_ptr);
+
+ if (!ret)
+ objc_class.reset();
+
+ return ret;
+ }
+
+ bool Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw)
+ {
+ class_ro.reset();
+ class_rw.reset();
+
+ Error error;
+ uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
+ if (!error.Success())
+ return false;
+
+ if (class_row_t_flags & RW_REALIZED)
+ {
+ class_rw.reset(new class_rw_t);
+
+ if (!class_rw->Read(process, objc_class.m_data_ptr))
+ {
+ class_rw.reset();
+ return false;
+ }
+
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, class_rw->m_ro_ptr))
+ {
+ class_rw.reset();
+ class_ro.reset();
+ return false;
+ }
+ }
+ else
+ {
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, objc_class.m_data_ptr))
+ {
+ class_ro.reset();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ AppleObjCRuntimeV2 &m_runtime; // The runtime, so we can read information lazily.
+ lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e., objects of this class type have this as their ISA)
+ ConstString m_name; // May be NULL
+};
+
+// tagged pointer descriptor
+class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
+{
+public:
+ ClassDescriptorV2Tagged (ConstString class_name,
+ uint64_t payload)
+ {
+ m_name = class_name;
+ if (!m_name)
+ {
+ m_valid = false;
+ return;
+ }
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0xF0ULL) >> 4;
+ m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+ }
+
+ ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+ uint64_t payload)
+ {
+ if (!actual_class_sp)
+ {
+ m_valid = false;
+ return;
+ }
+ m_name = actual_class_sp->GetClassName();
+ if (!m_name)
+ {
+ m_valid = false;
+ return;
+ }
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0x0FULL);
+ m_value_bits = (m_payload & ~0x0FULL) >> 4;
+ }
+
+ virtual ConstString
+ GetClassName ()
+ {
+ return m_name;
+ }
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetSuperclass ()
+ {
+ // tagged pointers can represent a class that has a superclass, but since that information is not
+ // stored in the object itself, we would have to query the runtime to discover the hierarchy
+ // for the time being, we skip this step in the interest of static discovery
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+
+ virtual bool
+ IsValid ()
+ {
+ return m_valid;
+ }
+
+ virtual bool
+ IsKVO ()
+ {
+ return false; // tagged pointers are not KVO'ed
+ }
+
+ virtual bool
+ IsCFType ()
+ {
+ return false; // tagged pointers are not CF objects
+ }
+
+ virtual bool
+ GetTaggedPointerInfo (uint64_t* info_bits = NULL,
+ uint64_t* value_bits = NULL,
+ uint64_t* payload = NULL)
+ {
+ if (info_bits)
+ *info_bits = GetInfoBits();
+ if (value_bits)
+ *value_bits = GetValueBits();
+ if (payload)
+ *payload = GetPayload();
+ return true;
+ }
+
+ virtual uint64_t
+ GetInstanceSize ()
+ {
+ return (IsValid() ? m_pointer_size : 0);
+ }
+
+ virtual ObjCLanguageRuntime::ObjCISA
+ GetISA ()
+ {
+ return 0; // tagged pointers have no ISA
+ }
+
+ // these calls are not part of any formal tagged pointers specification
+ virtual uint64_t
+ GetValueBits ()
+ {
+ return (IsValid() ? m_value_bits : 0);
+ }
+
+ virtual uint64_t
+ GetInfoBits ()
+ {
+ return (IsValid() ? m_info_bits : 0);
+ }
+
+ virtual uint64_t
+ GetPayload ()
+ {
+ return (IsValid() ? m_payload : 0);
+ }
+
+ virtual
+ ~ClassDescriptorV2Tagged ()
+ {}
+
+private:
+ ConstString m_name;
+ uint8_t m_pointer_size;
+ bool m_valid;
+ uint64_t m_info_bits;
+ uint64_t m_value_bits;
+ uint64_t m_payload;
+
+};
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
+{
+ ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
+ if (m_non_pointer_isa_cache_ap.get())
+ class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
+ if (!class_descriptor_sp)
+ class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
+ return class_descriptor_sp;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
+{
+ ClassDescriptorSP objc_class_sp;
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetValue().GetContextType() != Value::eContextTypeInvalid)
+ {
+ addr_t isa_pointer = valobj.GetPointerValue();
+
+ // tagged pointer
+ if (IsTaggedPointer(isa_pointer))
+ {
+ return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
+ }
+ else
+ {
+ ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ Error error;
+ ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+ if (isa != LLDB_INVALID_ADDRESS)
+ {
+ objc_class_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA (isa);
+ if (isa && !objc_class_sp)
+ {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
+ isa_pointer,
+ isa);
+ }
+ }
+ }
+ }
+ }
+ return objc_class_sp;
+}
+
+lldb::addr_t
+AppleObjCRuntimeV2::GetISAHashTablePointer ()
+{
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
+ {
+ Process *process = GetProcess();
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeData);
+ if (symbol)
+ {
+ lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
+
+ if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
+ {
+ Error error;
+ m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
+ }
+ }
+ }
+ return m_isa_hash_table_ptr;
+}
+
+bool
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
+{
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ExecutionContext exe_ctx;
+
+ ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+
+ if (!thread_sp)
+ return false;
+
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ if (!ast)
+ return false;
+
+ Address function_address;
+
+ StreamString errors;
+
+ const uint32_t addr_size = process->GetAddressByteSize();
+
+ Error err;
+
+ // Read the total number of classes from the hash table
+ const uint32_t num_classes = hash_table.GetCount();
+ if (num_classes == 0)
+ {
+ if (log)
+ log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
+ return false;
+ }
+
+ // Make some types for our arguments
+ clang_type_t clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ clang_type_t clang_void_pointer_type = ast->CreatePointerType(ast->GetBuiltInType_void());
+
+ if (!m_get_class_info_code.get())
+ {
+ m_get_class_info_code.reset (new ClangUtilityFunction (g_get_dynamic_class_info_body,
+ g_get_dynamic_class_info_name));
+
+ errors.Clear();
+
+ if (!m_get_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_class_info_code.reset();
+ }
+ }
+
+ if (m_get_class_info_code.get())
+ function_address.SetOffset(m_get_class_info_code->StartAddress());
+ else
+ return false;
+
+ ValueList arguments;
+
+ // Next make the runner function for our implementation utility function.
+ if (!m_get_class_info_function.get())
+ {
+ Value value;
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ arguments.PushValue (value);
+
+ m_get_class_info_function.reset(new ClangFunction (*m_process,
+ ast,
+ clang_uint32_t_type,
+ function_address,
+ arguments));
+
+ if (m_get_class_info_function.get() == NULL)
+ return false;
+
+ errors.Clear();
+
+ unsigned num_errors = m_get_class_info_function->CompileFunction(errors);
+ if (num_errors)
+ {
+ if (log)
+ log->Printf ("Error compiling function: \"%s\".", errors.GetData());
+ return false;
+ }
+
+ errors.Clear();
+
+ if (!m_get_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
+ {
+ if (log)
+ log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+ return false;
+ }
+ }
+ else
+ {
+ arguments = m_get_class_info_function->GetArgumentValues ();
+ }
+
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
+ ePermissionsReadable | ePermissionsWritable,
+ err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Mutex::Locker locker(m_get_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+
+ bool success = false;
+
+ errors.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (m_get_class_info_function->WriteFunctionArguments (exe_ctx,
+ m_get_class_info_args,
+ function_address,
+ arguments,
+ errors))
+ {
+ bool stop_others = true;
+ bool try_all_threads = false;
+ bool unwind_on_error = true;
+ bool ignore_breakpoints = true;
+
+ Value return_value;
+ return_value.SetValueType (Value::eValueTypeScalar);
+ return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ return_value.GetScalar() = 0;
+
+ errors.Clear();
+
+ // Run the function
+ ExecutionResults results = m_get_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_class_info_args,
+ errors,
+ stop_others,
+ UTILITY_FUNCTION_TIMEOUT_USEC,
+ try_all_threads,
+ unwind_on_error,
+ ignore_breakpoints,
+ return_value);
+
+ if (results == eExecutionCompleted)
+ {
+ // The result is the number of ClassInfo structures that were filled in
+ uint32_t num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes\n",num_class_infos);
+ if (num_class_infos > 0)
+ {
+ // Read the ClassInfo structures
+ DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
+ {
+ DataExtractor class_infos_data (buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(),
+ addr_size);
+ ParseClassInfoArray (class_infos_data, num_class_infos);
+ }
+ }
+ success = true;
+ }
+ else
+ {
+ if (log)
+ log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ }
+
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return success;
+}
+
+void
+AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
+{
+ // Parses an array of "num_class_infos" packed ClassInfo structures:
+ //
+ // struct ClassInfo
+ // {
+ // Class isa;
+ // uint32_t hash;
+ // } __attribute__((__packed__));
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Iterate through all ClassInfo structures
+ lldb::offset_t offset = 0;
+ for (uint32_t i=0; i<num_class_infos; ++i)
+ {
+ ObjCISA isa = data.GetPointer(&offset);
+
+ if (isa == 0)
+ {
+ if (log)
+ log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
+ continue;
+ }
+ // Check if we already know about this ISA, if we do, the info will
+ // never change, so we can just skip it.
+ if (ISAIsCached(isa))
+ {
+ offset += 4;
+ }
+ else
+ {
+ // Read the 32 bit hash for the class name
+ const uint32_t name_hash = data.GetU32(&offset);
+ ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
+ AddClass (isa, descriptor_sp, name_hash);
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x", isa, name_hash);
+ }
+ }
+}
+
+bool
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
+{
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ ExecutionContext exe_ctx;
+
+ ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+
+ if (!thread_sp)
+ return false;
+
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ if (!ast)
+ return false;
+
+ Address function_address;
+
+ StreamString errors;
+
+ const uint32_t addr_size = process->GetAddressByteSize();
+
+ Error err;
+
+ const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
+
+ if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ // Read the total number of classes from the hash table
+ const uint32_t num_classes = 16*1024;
+ if (num_classes == 0)
+ {
+ if (log)
+ log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
+ return false;
+ }
+
+ // Make some types for our arguments
+ clang_type_t clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ clang_type_t clang_void_pointer_type = ast->CreatePointerType(ast->GetBuiltInType_void());
+
+ if (!m_get_shared_cache_class_info_code.get())
+ {
+ m_get_shared_cache_class_info_code.reset (new ClangUtilityFunction (g_get_shared_cache_class_info_body,
+ g_get_shared_cache_class_info_name));
+
+ errors.Clear();
+
+ if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_shared_cache_class_info_code.reset();
+ }
+ }
+
+ if (m_get_shared_cache_class_info_code.get())
+ function_address.SetOffset(m_get_shared_cache_class_info_code->StartAddress());
+ else
+ return false;
+
+ ValueList arguments;
+
+ // Next make the runner function for our implementation utility function.
+ if (!m_get_shared_cache_class_info_function.get())
+ {
+ Value value;
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ arguments.PushValue (value);
+
+ value.SetValueType (Value::eValueTypeScalar);
+ value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ arguments.PushValue (value);
+
+ m_get_shared_cache_class_info_function.reset(new ClangFunction (*m_process,
+ ast,
+ clang_uint32_t_type,
+ function_address,
+ arguments));
+
+ if (m_get_shared_cache_class_info_function.get() == NULL)
+ return false;
+
+ errors.Clear();
+
+ unsigned num_errors = m_get_shared_cache_class_info_function->CompileFunction(errors);
+ if (num_errors)
+ {
+ if (log)
+ log->Printf ("Error compiling function: \"%s\".", errors.GetData());
+ return false;
+ }
+
+ errors.Clear();
+
+ if (!m_get_shared_cache_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
+ {
+ if (log)
+ log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+ return false;
+ }
+ }
+ else
+ {
+ arguments = m_get_shared_cache_class_info_function->GetArgumentValues ();
+ }
- //printf("name_pointer: %llx\n", name_pointer);
- char cstr[512];
- if (m_process->ReadCStringFromMemory(name_pointer, cstr, sizeof(cstr), error) > 0)
- {
- if (::strstr(cstr, "NSKVONotify") == cstr)
- {
- // the ObjC runtime implements KVO by replacing the isa with a special
- // NSKVONotifying_className that overrides the relevant methods
- // the side effect on us is that getting the typename for a KVO-ed object
- // will return the swizzled class instead of the actual one
- // this swizzled class is a descendant of the real class, so just
- // return the parent type and all should be fine
- ConstString class_name = GetActualTypeName(GetParentClass(isa));
- m_isa_to_name_cache[isa] = class_name;
- return class_name;
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
+ ePermissionsReadable | ePermissionsWritable,
+ err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+
+ bool success = false;
+
+ errors.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (m_get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
+ m_get_shared_cache_class_info_args,
+ function_address,
+ arguments,
+ errors))
+ {
+ bool stop_others = true;
+ bool try_all_threads = false;
+ bool unwind_on_error = true;
+ bool ignore_breakpoints = true;
+
+ Value return_value;
+ return_value.SetValueType (Value::eValueTypeScalar);
+ return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ return_value.GetScalar() = 0;
+
+ errors.Clear();
+
+ // Run the function
+ ExecutionResults results = m_get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_shared_cache_class_info_args,
+ errors,
+ stop_others,
+ UTILITY_FUNCTION_TIMEOUT_USEC,
+ try_all_threads,
+ unwind_on_error,
+ ignore_breakpoints,
+ return_value);
+
+ if (results == eExecutionCompleted)
+ {
+ // The result is the number of ClassInfo structures that were filled in
+ uint32_t num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
+ if (num_class_infos > 0)
+ {
+ // Read the ClassInfo structures
+ DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr,
+ buffer.GetBytes(),
+ buffer.GetByteSize(),
+ err) == buffer.GetByteSize())
+ {
+ DataExtractor class_infos_data (buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(),
+ addr_size);
+
+ ParseClassInfoArray (class_infos_data, num_class_infos);
+ }
+ }
+ success = true;
}
else
{
- ConstString class_name = ConstString(cstr);
- m_isa_to_name_cache[isa] = class_name;
- return class_name;
+ if (log)
+ log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
}
}
else
- return g_unknown;
+ {
+ if (log)
+ log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ }
+
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return success;
+}
+
+
+bool
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
+{
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ uint32_t num_map_table_isas = 0;
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp)
+ {
+ for (RemoteNXMapTable::element elt : hash_table)
+ {
+ ++num_map_table_isas;
+
+ if (ISAIsCached(elt.second))
+ continue;
+
+ ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
+
+ AddClass (elt.second, descriptor_sp, elt.first.AsCString());
+ }
+ }
+
+ return num_map_table_isas > 0;
}
-ObjCLanguageRuntime::ObjCISA
-AppleObjCRuntimeV2::GetParentClass(ObjCLanguageRuntime::ObjCISA isa)
+lldb::addr_t
+AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
{
- if (!IsValidISA(isa))
- return 0;
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp)
+ {
+ ObjectFile *objc_object = objc_module_sp->GetObjectFile();
+
+ if (objc_object)
+ {
+ SectionList *section_list = objc_object->GetSectionList();
+
+ if (section_list)
+ {
+ SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
+
+ if (text_segment_sp)
+ {
+ SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
+
+ if (objc_opt_section_sp)
+ {
+ return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
+ }
+ }
+ }
+ }
+ }
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
+void
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+ // Else we need to check with our process to see when the map was updated.
+ Process *process = GetProcess();
+
+ if (process)
+ {
+ RemoteNXMapTable hash_table;
+
+ // Update the process stop ID that indicates the last time we updated the
+ // map, wether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
+ return;
+
+ m_hash_signature.UpdateSignature (hash_table);
+
+ // Grab the dynamicly loaded objc classes from the hash table in memory
+ UpdateISAToDescriptorMapDynamic(hash_table);
+
+ // Now get the objc classes that are baked into the Objective C runtime
+ // in the shared cache, but only once per process as this data never
+ // changes
+ if (!m_loaded_objc_opt)
+ UpdateISAToDescriptorMapSharedCache();
+ }
+ else
+ {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
+}
+
+
+// TODO: should we have a transparent_kvo parameter here to say if we
+// want to replace the KVO swizzled class with the actual user-level type?
+ConstString
+AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
+{
if (isa == g_objc_Tagged_ISA)
- return 0;
+ {
+ static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
+ return g_objc_tagged_isa_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSAtom)
+ {
+ static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
+ return g_objc_tagged_isa_nsatom_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSNumber)
+ {
+ static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
+ return g_objc_tagged_isa_nsnumber_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDateTS)
+ {
+ static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
+ return g_objc_tagged_isa_nsdatets_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSManagedObject)
+ {
+ static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
+ return g_objc_tagged_isa_nsmanagedobject_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDate)
+ {
+ static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
+ return g_objc_tagged_isa_nsdate_name;
+ }
+ return ObjCLanguageRuntime::GetActualTypeName(isa);
+}
+
+TypeVendor *
+AppleObjCRuntimeV2::GetTypeVendor()
+{
+ if (!m_type_vendor_ap.get())
+ m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
+
+ return m_type_vendor_ap.get();
+}
+
+lldb::addr_t
+AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
+{
+ lldb::addr_t ret = LLDB_INVALID_ADDRESS;
+
+ const char *name_cstr = name.AsCString();
+
+ if (name_cstr)
+ {
+ llvm::StringRef name_strref(name_cstr);
+
+ static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
+ static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
+
+ if (name_strref.startswith(ivar_prefix))
+ {
+ llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
+ std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
+
+ if (class_and_ivar.first.size() && class_and_ivar.second.size())
+ {
+ const ConstString class_name_cs(class_and_ivar.first);
+ ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor)
+ {
+ const ConstString ivar_name_cs(class_and_ivar.second);
+ const char *ivar_name_cstr = ivar_name_cs.AsCString();
+
+ auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
+ {
+ if (!strcmp(name, ivar_name_cstr))
+ {
+ ret = offset_addr;
+ return true;
+ }
+ return false;
+ };
+
+ descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
+ std::function<bool (const char *, const char *)>(nullptr),
+ std::function<bool (const char *, const char *)>(nullptr),
+ ivar_func);
+ }
+ }
+ }
+ else if (name_strref.startswith(class_prefix))
+ {
+ llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
+ const ConstString class_name_cs(class_skipped_prefix);
+ ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor)
+ ret = descriptor->GetISA();
+ }
+ }
+
+ return ret;
+}
+
+AppleObjCRuntimeV2::NonPointerISACache*
+AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
+
+ Error error;
- ISAToParentIterator found = m_isa_to_parent_cache.find(isa);
- ISAToParentIterator end = m_isa_to_parent_cache.end();
+ auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_magic_value"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_isa_class_mask"),
+ objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
- if (found != end)
- return found->second;
+ return new NonPointerISACache(runtime,
+ objc_debug_isa_class_mask,
+ objc_debug_isa_magic_mask,
+ objc_debug_isa_magic_value);
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendor*
+AppleObjCRuntimeV2::TaggedPointerVendor::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
+{
+ Process* process(runtime.GetProcess());
- uint8_t pointer_size = m_process->GetAddressByteSize();
Error error;
- /*
- struct class_t *isa;
---> struct class_t *superclass;
- */
- addr_t parent_pointer = isa + pointer_size;
- //printf("rw_pointer: %llx\n", rw_pointer);
-
- uint64_t parent_isa = m_process->ReadUnsignedIntegerFromMemory(parent_pointer,
- pointer_size,
- 0,
+
+ auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_mask"),
+ objc_module_sp,
error);
if (error.Fail())
- return 0;
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_shift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_slot_mask"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_lshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_payload_rshift"),
+ objc_module_sp,
+ error,
+ true,
+ 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
+ ConstString("objc_debug_taggedpointer_classes"),
+ objc_module_sp,
+ error,
+ false);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+
+ // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
+
+ return new TaggedPointerVendorRuntimeAssisted(runtime,
+ objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_slot_shift,
+ objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_classes);
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & 1);
+}
+
+// we use the version of Foundation to make assumptions about the ObjC runtime on a target
+uint32_t
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetFoundationVersion (Target &target)
+{
+ const ModuleList& modules = target.GetImages();
+ uint32_t major = UINT32_MAX;
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
+ {
+ lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
+ if (!module_sp)
+ continue;
+ if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
+ {
+ module_sp->GetVersion(&major,1);
+ break;
+ }
+ }
+ return major;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
+{
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ Process* process(m_runtime.GetProcess());
+
+ if (m_Foundation_version == 0)
+ m_Foundation_version = GetFoundationVersion(process->GetTarget());
+
+ if (m_Foundation_version == UINT32_MAX)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
- m_isa_to_parent_cache[isa] = parent_isa;
+ uint64_t class_bits = (ptr & 0xE) >> 1;
+ ConstString name;
- return parent_isa;
+ // TODO: make a table
+ if (m_Foundation_version >= 900)
+ {
+ switch (class_bits)
+ {
+ case 0:
+ name = ConstString("NSAtom");
+ break;
+ case 3:
+ name = ConstString("NSNumber");
+ break;
+ case 4:
+ name = ConstString("NSDateTS");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ else
+ {
+ switch (class_bits)
+ {
+ case 1:
+ name = ConstString("NSNumber");
+ break;
+ case 5:
+ name = ConstString("NSManagedObject");
+ break;
+ case 6:
+ name = ConstString("NSDate");
+ break;
+ case 7:
+ name = ConstString("NSDateTS");
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+ }
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
+}
+
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes) :
+TaggedPointerVendor(runtime),
+m_cache(),
+m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
+m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
+m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
+m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
+m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
+m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
+{
+}
+
+bool
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
+{
+ return (ptr & m_objc_debug_taggedpointer_mask) != 0;
}
-SymbolVendor *
-AppleObjCRuntimeV2::GetSymbolVendor()
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
{
- if (!m_symbol_vendor_ap.get())
- m_symbol_vendor_ap.reset(new AppleObjCSymbolVendor(m_process));
+ ClassDescriptorSP actual_class_descriptor_sp;
+ uint64_t data_payload;
+
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
+
+ CacheIterator iterator = m_cache.find(slot),
+ end = m_cache.end();
+ if (iterator != end)
+ {
+ actual_class_descriptor_sp = iterator->second;
+ }
+ else
+ {
+ Process* process(m_runtime.GetProcess());
+ uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
+ return nullptr;
+ actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_cache[slot] = actual_class_descriptor_sp;
+ }
+
+ data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
- return m_symbol_vendor_ap.get();
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+}
+
+AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value) :
+m_runtime(runtime),
+m_cache(),
+m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
+m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
+m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
+{
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP
+AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
+{
+ ObjCISA real_isa = 0;
+ if (EvaluateNonPointerISA(isa, real_isa) == false)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ auto cache_iter = m_cache.find(real_isa);
+ if (cache_iter != m_cache.end())
+ return cache_iter->second;
+ auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
+ if (descriptor_sp) // cache only positive matches since the table might grow
+ m_cache[real_isa] = descriptor_sp;
+ return descriptor_sp;
+}
+
+bool
+AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
+{
+ if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
+ return false;
+ if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
+ {
+ ret_isa = isa & m_objc_debug_isa_class_mask;
+ return (ret_isa != 0); // this is a pointer so 0 is not a valid value
+ }
+ return false;
}
Modified: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h?rev=183468&r1=183467&r2=183468&view=diff
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h Thu Jun 6 19:06:43 2013
@@ -14,6 +14,7 @@
// C++ Includes
#include <map>
+#include <memory>
// Other libraries and framework includes
// Project includes
@@ -21,13 +22,15 @@
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "AppleObjCRuntime.h"
+class RemoteNXMapTable;
+
namespace lldb_private {
class AppleObjCRuntimeV2 :
public AppleObjCRuntime
{
public:
- virtual ~AppleObjCRuntimeV2() { }
+ virtual ~AppleObjCRuntimeV2();
// These are generic runtime functions:
virtual bool
@@ -52,15 +55,15 @@ public:
static lldb_private::LanguageRuntime *
CreateInstance (Process *process, lldb::LanguageType language);
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual const char *
+ virtual ConstString
GetPluginName();
- virtual const char *
- GetShortPluginName();
-
virtual uint32_t
GetPluginVersion();
@@ -72,29 +75,35 @@ public:
virtual size_t
GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name);
+
+ virtual void
+ UpdateISAToDescriptorMapIfNeeded();
- virtual bool
- IsValidISA (ObjCLanguageRuntime::ObjCISA isa)
- {
- return (isa != 0);
- }
-
- // this is not a valid ISA in the sense that no valid
- // class pointer can live at address 1. we use it to refer to
- // tagged types, where the ISA must be dynamically determined
+ // none of these are valid ISAs - we use them to infer the type
+ // of tagged pointers - if we have something meaningful to say
+ // we report an actual type - otherwise, we just say tagged
+ // there is no connection between the values here and the tagged pointers map
static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
-
- virtual ObjCLanguageRuntime::ObjCISA
- GetISA(ValueObject& valobj);
-
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 5;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
+
virtual ConstString
GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa);
- virtual ObjCLanguageRuntime::ObjCISA
- GetParentClass(ObjCLanguageRuntime::ObjCISA isa);
+ virtual ClassDescriptorSP
+ GetClassDescriptor (ValueObject& in_value);
- virtual SymbolVendor *
- GetSymbolVendor();
+ virtual ClassDescriptorSP
+ GetClassDescriptor (ObjCISA isa);
+
+ virtual TypeVendor *
+ GetTypeVendor();
+
+ virtual lldb::addr_t
+ LookupRuntimeSymbol (const ConstString &name);
protected:
virtual lldb::BreakpointResolverSP
@@ -102,33 +111,178 @@ protected:
private:
- typedef std::map<ObjCLanguageRuntime::ObjCISA, ConstString> ISAToNameCache;
- typedef std::map<ObjCLanguageRuntime::ObjCISA, ObjCLanguageRuntime::ObjCISA> ISAToParentCache;
+ class HashTableSignature
+ {
+ public:
+ HashTableSignature ();
+
+ bool
+ NeedsUpdate (Process *process,
+ AppleObjCRuntimeV2 *runtime,
+ RemoteNXMapTable &hash_table);
+
+ void
+ UpdateSignature (const RemoteNXMapTable &hash_table);
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
+
+ class NonPointerISACache
+ {
+ public:
+ static NonPointerISACache*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (ObjCISA isa);
+ private:
+ NonPointerISACache (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value);
+
+ bool
+ EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa);
+
+ AppleObjCRuntimeV2& m_runtime;
+ std::map<ObjCISA,ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
+ uint64_t m_objc_debug_isa_class_mask;
+ uint64_t m_objc_debug_isa_magic_mask;
+ uint64_t m_objc_debug_isa_magic_value;
+
+ DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
+ };
+
+ class TaggedPointerVendor
+ {
+ public:
+ static TaggedPointerVendor*
+ CreateInstance (AppleObjCRuntimeV2& runtime,
+ const lldb::ModuleSP& objc_module_sp);
+
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr) = 0;
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr) = 0;
+
+ virtual
+ ~TaggedPointerVendor () { }
+ protected:
+ AppleObjCRuntimeV2& m_runtime;
+
+ TaggedPointerVendor (AppleObjCRuntimeV2& runtime) :
+ m_runtime(runtime)
+ {
+ }
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor);
+ };
+
+ class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendor
+ {
+ public:
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr);
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr);
+ protected:
+ TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
+ uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes);
+
+ typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+ typedef Cache::iterator CacheIterator;
+ Cache m_cache;
+ uint64_t m_objc_debug_taggedpointer_mask;
+ uint32_t m_objc_debug_taggedpointer_slot_shift;
+ uint32_t m_objc_debug_taggedpointer_slot_mask;
+ uint32_t m_objc_debug_taggedpointer_payload_lshift;
+ uint32_t m_objc_debug_taggedpointer_payload_rshift;
+ lldb::addr_t m_objc_debug_taggedpointer_classes;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
+ };
- typedef ISAToNameCache::iterator ISAToNameIterator;
- typedef ISAToParentCache::iterator ISAToParentIterator;
+ class TaggedPointerVendorLegacy : public TaggedPointerVendor
+ {
+ public:
+ virtual bool
+ IsPossibleTaggedPointer (lldb::addr_t ptr);
+
+ virtual ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor (lldb::addr_t ptr);
+ protected:
+ TaggedPointerVendorLegacy (AppleObjCRuntimeV2& runtime) :
+ TaggedPointerVendor (runtime),
+ m_Foundation_version(0)
+ {
+ }
+
+ static uint32_t
+ GetFoundationVersion (Target& target);
+
+ uint32_t m_Foundation_version;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendor;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
+ };
- AppleObjCRuntimeV2 (Process *process,
+ AppleObjCRuntimeV2 (Process *process,
const lldb::ModuleSP &objc_module_sp);
bool
IsTaggedPointer(lldb::addr_t ptr);
- bool RunFunctionToFindClassName (lldb::addr_t class_addr, Thread *thread, char *name_dst, size_t max_name_len);
+ lldb::addr_t
+ GetISAHashTablePointer ();
+
+ bool
+ UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table);
- bool m_has_object_getClass;
- std::auto_ptr<ClangFunction> m_get_class_name_function;
- std::auto_ptr<ClangUtilityFunction> m_get_class_name_code;
- lldb::addr_t m_get_class_name_args;
- Mutex m_get_class_name_args_mutex;
+ bool
+ UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
- ISAToNameCache m_isa_to_name_cache;
- ISAToParentCache m_isa_to_parent_cache;
+ void
+ ParseClassInfoArray (const lldb_private::DataExtractor &data,
+ uint32_t num_class_infos);
- std::auto_ptr<SymbolVendor> m_symbol_vendor_ap;
+ bool
+ UpdateISAToDescriptorMapSharedCache ();
+
+ lldb::addr_t
+ GetSharedCacheReadOnlyAddress();
- static const char *g_find_class_name_function_name;
- static const char *g_find_class_name_function_body;
+ std::unique_ptr<ClangFunction> m_get_class_info_function;
+ std::unique_ptr<ClangUtilityFunction> m_get_class_info_code;
+ lldb::addr_t m_get_class_info_args;
+ Mutex m_get_class_info_args_mutex;
+
+ std::unique_ptr<ClangFunction> m_get_shared_cache_class_info_function;
+ std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code;
+ lldb::addr_t m_get_shared_cache_class_info_args;
+ Mutex m_get_shared_cache_class_info_args_mutex;
+
+ std::unique_ptr<TypeVendor> m_type_vendor_ap;
+ lldb::addr_t m_isa_hash_table_ptr;
+ HashTableSignature m_hash_signature;
+ bool m_has_object_getClass;
+ bool m_loaded_objc_opt;
+ std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
+ std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
};
} // namespace lldb_private
Removed: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.cpp (removed)
@@ -1,82 +0,0 @@
-//===-- AppleObjCSymbolVendor.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AppleObjCSymbolVendor.h"
-
-#include "lldb/Core/Log.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "clang/AST/ASTContext.h"
-
-using namespace lldb_private;
-
-AppleObjCSymbolVendor::AppleObjCSymbolVendor(Process *process) :
- SymbolVendor(lldb::ModuleSP()),
- m_process(process->shared_from_this()),
- m_ast_ctx(process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str())
-{
-}
-
-uint32_t
-AppleObjCSymbolVendor::FindTypes (const SymbolContext& sc,
- const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- TypeList& types)
-{
- lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); // FIXME - a more appropriate log channel?
-
- if (log)
- log->Printf("ObjC SymbolVendor asked for '%s'",
- name.AsCString());
-
- if (!append)
- types.Clear();
-
- uint32_t ret = 0;
-
- ModuleList &target_modules = m_process->GetTarget().GetImages();
- Mutex::Locker modules_locker(target_modules.GetMutex());
-
- for (size_t image_index = 0, end_index = target_modules.GetSize();
- image_index < end_index;
- ++image_index)
- {
- Module *image = target_modules.GetModulePointerAtIndexUnlocked(image_index);
-
- if (!image)
- continue;
-
- SymbolVendor *symbol_vendor = image->GetSymbolVendor();
-
- if (!symbol_vendor)
- continue;
-
- SymbolFile *symbol_file = image->GetSymbolVendor()->GetSymbolFile();
-
- // Don't use a symbol file if it actually has types. We are specifically
- // looking for something in runtime information, not from debug information,
- // as the data in debug information will get parsed by the debug info
- // symbol files. So we veto any symbol file that has actual variable
- // type parsing abilities.
- if (symbol_file == NULL || (symbol_file->GetAbilities() & SymbolFile::VariableTypes))
- continue;
-
- const bool inferior_append = true;
-
- ret += symbol_file->FindTypes (sc, name, namespace_decl, inferior_append, max_matches - ret, types);
-
- if (ret >= max_matches)
- break;
- }
-
- return ret;
-}
Removed: lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h?rev=183467&view=auto
==============================================================================
--- lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h (original)
+++ lldb/branches/lldb-platform-work/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCSymbolVendor.h (removed)
@@ -1,47 +0,0 @@
-//===-- AppleObjCSymbolVendor.h ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_AppleObjCSymbolVendor_h_
-#define liblldb_AppleObjCSymbolVendor_h_
-
-// C Includes
-// C++ Includes
-
-#include <map>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/SymbolFile.h"
-
-namespace lldb_private {
-
-class AppleObjCSymbolVendor : public SymbolVendor
-{
-public:
- AppleObjCSymbolVendor(Process* process);
-
- virtual uint32_t
- FindTypes (const SymbolContext& sc,
- const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- TypeList& types);
-
-private:
- lldb::ProcessSP m_process;
- ClangASTContext m_ast_ctx;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_AppleObjCSymbolVendor_h_
More information about the llvm-branch-commits
mailing list