Refactor DexFile::DecodeDebugInfo.
Split the method into two - one for locals and one for positions.
All uses of the method request only one of the two and it makes the
code slightly cleaner. The position variant requires fewer parameters.
Expose additional line table information which was previously ignored
by the decode method (prologue, epilogue, source file).
Change-Id: Idf8ba98fa58ea0d2103932b5cc0af81365885107
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 51f57c3..62c9d25 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1536,10 +1536,10 @@
int numItems;
JDWP::ExpandBuf* pReply;
- static bool Callback(void* context, uint32_t address, uint32_t line_number) {
+ static bool Callback(void* context, const DexFile::PositionInfo& entry) {
DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
- expandBufAdd8BE(pContext->pReply, address);
- expandBufAdd4BE(pContext->pReply, line_number);
+ expandBufAdd8BE(pContext->pReply, entry.address_);
+ expandBufAdd4BE(pContext->pReply, entry.line_);
pContext->numItems++;
return false;
}
@@ -1569,8 +1569,7 @@
context.pReply = pReply;
if (code_item != nullptr) {
- m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
- DebugCallbackContext::Callback, nullptr, &context);
+ m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context);
}
JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems);
@@ -1584,25 +1583,26 @@
size_t variable_count;
bool with_generic;
- static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress,
- const char* name, const char* descriptor, const char* signature)
+ static void Callback(void* context, const DexFile::LocalInfo& entry)
SHARED_REQUIRES(Locks::mutator_lock_) {
DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
+ uint16_t slot = entry.reg_;
VLOG(jdwp) << StringPrintf(" %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d",
- pContext->variable_count, startAddress, endAddress - startAddress,
- name, descriptor, signature, slot,
+ pContext->variable_count, entry.start_address_,
+ entry.end_address_ - entry.start_address_,
+ entry.name_, entry.descriptor_, entry.signature_, slot,
MangleSlot(slot, pContext->method));
slot = MangleSlot(slot, pContext->method);
- expandBufAdd8BE(pContext->pReply, startAddress);
- expandBufAddUtf8String(pContext->pReply, name);
- expandBufAddUtf8String(pContext->pReply, descriptor);
+ expandBufAdd8BE(pContext->pReply, entry.start_address_);
+ expandBufAddUtf8String(pContext->pReply, entry.name_);
+ expandBufAddUtf8String(pContext->pReply, entry.descriptor_);
if (pContext->with_generic) {
- expandBufAddUtf8String(pContext->pReply, signature);
+ expandBufAddUtf8String(pContext->pReply, entry.signature_);
}
- expandBufAdd4BE(pContext->pReply, endAddress - startAddress);
+ expandBufAdd4BE(pContext->pReply, entry.end_address_- entry.start_address_);
expandBufAdd4BE(pContext->pReply, slot);
++pContext->variable_count;
@@ -1627,8 +1627,8 @@
const DexFile::CodeItem* code_item = m->GetCodeItem();
if (code_item != nullptr) {
- m->GetDexFile()->DecodeDebugInfo(
- code_item, m->IsStatic(), m->GetDexMethodIndex(), nullptr, DebugCallbackContext::Callback,
+ m->GetDexFile()->DecodeDebugLocalInfo(
+ code_item, m->IsStatic(), m->GetDexMethodIndex(), DebugCallbackContext::Callback,
&context);
}
@@ -3716,19 +3716,19 @@
code_item_(code_item), last_pc_valid(false), last_pc(0) {
}
- static bool Callback(void* raw_context, uint32_t address, uint32_t line_number_cb) {
+ static bool Callback(void* raw_context, const DexFile::PositionInfo& entry) {
DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context);
- if (static_cast<int32_t>(line_number_cb) == context->line_number_) {
+ if (static_cast<int32_t>(entry.line_) == context->line_number_) {
if (!context->last_pc_valid) {
// Everything from this address until the next line change is ours.
- context->last_pc = address;
+ context->last_pc = entry.address_;
context->last_pc_valid = true;
}
// Otherwise, if we're already in a valid range for this line,
// just keep going (shouldn't really happen)...
} else if (context->last_pc_valid) { // and the line number is new
// Add everything from the last entry up until here to the set
- for (uint32_t dex_pc = context->last_pc; dex_pc < address; ++dex_pc) {
+ for (uint32_t dex_pc = context->last_pc; dex_pc < entry.address_; ++dex_pc) {
context->single_step_control_->AddDexPc(dex_pc);
}
context->last_pc_valid = false;
@@ -3769,8 +3769,7 @@
if (m != nullptr && !m->IsNative()) {
const DexFile::CodeItem* const code_item = m->GetCodeItem();
DebugCallbackContext context(single_step_control, line_number, code_item);
- m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
- DebugCallbackContext::Callback, nullptr, &context);
+ m->GetDexFile()->DecodeDebugPositionInfo(code_item, DebugCallbackContext::Callback, &context);
}
// Activate single-step in the thread.
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 30d921a..e62aa04 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -767,8 +767,7 @@
// A method with no line number info should return -1
LineNumFromPcContext context(rel_pc, -1);
- DecodeDebugInfo(code_item, method->IsStatic(), method->GetDexMethodIndex(), LineNumForPcCb,
- nullptr, &context);
+ DecodeDebugPositionInfo(code_item, LineNumForPcCb, &context);
return context.line_num_;
}
@@ -805,45 +804,48 @@
}
}
-void DexFile::DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
- DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
- void* context, const uint8_t* stream, LocalInfo* local_in_reg)
- const {
- uint32_t line = DecodeUnsignedLeb128(&stream);
- uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
- uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
- uint32_t address = 0;
- bool need_locals = (local_cb != nullptr);
+bool DexFile::DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
+ DexDebugNewLocalCb local_cb, void* context) const {
+ DCHECK(local_cb != nullptr);
+ if (code_item == nullptr) {
+ return false;
+ }
+ const uint8_t* stream = GetDebugInfoStream(code_item);
+ if (stream == nullptr) {
+ return false;
+ }
+ std::vector<LocalInfo> local_in_reg(code_item->registers_size_);
+ uint16_t arg_reg = code_item->registers_size_ - code_item->ins_size_;
if (!is_static) {
- if (need_locals) {
- const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
- local_in_reg[arg_reg].name_ = "this";
- local_in_reg[arg_reg].descriptor_ = descriptor;
- local_in_reg[arg_reg].signature_ = nullptr;
- local_in_reg[arg_reg].start_address_ = 0;
- local_in_reg[arg_reg].is_live_ = true;
- }
+ const char* descriptor = GetMethodDeclaringClassDescriptor(GetMethodId(method_idx));
+ local_in_reg[arg_reg].name_ = "this";
+ local_in_reg[arg_reg].descriptor_ = descriptor;
+ local_in_reg[arg_reg].signature_ = nullptr;
+ local_in_reg[arg_reg].start_address_ = 0;
+ local_in_reg[arg_reg].reg_ = arg_reg;
+ local_in_reg[arg_reg].is_live_ = true;
arg_reg++;
}
DexFileParameterIterator it(*this, GetMethodPrototype(GetMethodId(method_idx)));
- for (uint32_t i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
+ DecodeUnsignedLeb128(&stream); // Line.
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ uint32_t i;
+ for (i = 0; i < parameters_size && it.HasNext(); ++i, it.Next()) {
if (arg_reg >= code_item->registers_size_) {
LOG(ERROR) << "invalid stream - arg reg >= reg size (" << arg_reg
<< " >= " << code_item->registers_size_ << ") in " << GetLocation();
- return;
+ return false;
}
- uint32_t id = DecodeUnsignedLeb128P1(&stream);
+ uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
const char* descriptor = it.GetDescriptor();
- if (need_locals && id != kDexNoIndex) {
- const char* name = StringDataByIdx(id);
- local_in_reg[arg_reg].name_ = name;
- local_in_reg[arg_reg].descriptor_ = descriptor;
- local_in_reg[arg_reg].signature_ = nullptr;
- local_in_reg[arg_reg].start_address_ = address;
- local_in_reg[arg_reg].is_live_ = true;
- }
+ local_in_reg[arg_reg].name_ = StringDataByIdx(name_idx);
+ local_in_reg[arg_reg].descriptor_ = descriptor;
+ local_in_reg[arg_reg].signature_ = nullptr;
+ local_in_reg[arg_reg].start_address_ = 0;
+ local_in_reg[arg_reg].reg_ = arg_reg;
+ local_in_reg[arg_reg].is_live_ = true;
switch (*descriptor) {
case 'D':
case 'J':
@@ -854,152 +856,188 @@
break;
}
}
-
- if (it.HasNext()) {
+ if (i != parameters_size || it.HasNext()) {
LOG(ERROR) << "invalid stream - problem with parameter iterator in " << GetLocation()
<< " for method " << PrettyMethod(method_idx, *this);
- return;
+ return false;
}
+ uint32_t address = 0;
for (;;) {
uint8_t opcode = *stream++;
- uint16_t reg;
- uint32_t name_idx;
- uint32_t descriptor_idx;
- uint32_t signature_idx = 0;
-
switch (opcode) {
case DBG_END_SEQUENCE:
- return;
-
+ // Emit all variables which are still alive at the end of the method.
+ for (uint16_t reg = 0; reg < code_item->registers_size_; reg++) {
+ if (local_in_reg[reg].is_live_) {
+ local_in_reg[reg].end_address_ = code_item->insns_size_in_code_units_;
+ local_cb(context, local_in_reg[reg]);
+ }
+ }
+ return true;
case DBG_ADVANCE_PC:
address += DecodeUnsignedLeb128(&stream);
break;
-
case DBG_ADVANCE_LINE:
- line += DecodeSignedLeb128(&stream);
+ DecodeSignedLeb128(&stream); // Line.
break;
-
case DBG_START_LOCAL:
- case DBG_START_LOCAL_EXTENDED:
- reg = DecodeUnsignedLeb128(&stream);
- if (reg > code_item->registers_size_) {
- LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
+ case DBG_START_LOCAL_EXTENDED: {
+ uint16_t reg = DecodeUnsignedLeb128(&stream);
+ if (reg >= code_item->registers_size_) {
+ LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
<< code_item->registers_size_ << ") in " << GetLocation();
- return;
+ return false;
}
- name_idx = DecodeUnsignedLeb128P1(&stream);
- descriptor_idx = DecodeUnsignedLeb128P1(&stream);
+ uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
+ uint32_t descriptor_idx = DecodeUnsignedLeb128P1(&stream);
+ uint32_t signature_idx = kDexNoIndex;
if (opcode == DBG_START_LOCAL_EXTENDED) {
signature_idx = DecodeUnsignedLeb128P1(&stream);
}
// Emit what was previously there, if anything
- if (need_locals) {
- InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
+ if (local_in_reg[reg].is_live_) {
+ local_in_reg[reg].end_address_ = address;
+ local_cb(context, local_in_reg[reg]);
+ }
- local_in_reg[reg].name_ = StringDataByIdx(name_idx);
- local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
- local_in_reg[reg].signature_ =
- (opcode == DBG_START_LOCAL_EXTENDED) ? StringDataByIdx(signature_idx)
- : nullptr;
+ local_in_reg[reg].name_ = StringDataByIdx(name_idx);
+ local_in_reg[reg].descriptor_ = StringByTypeIdx(descriptor_idx);
+ local_in_reg[reg].signature_ = StringDataByIdx(signature_idx);
+ local_in_reg[reg].start_address_ = address;
+ local_in_reg[reg].reg_ = reg;
+ local_in_reg[reg].is_live_ = true;
+ break;
+ }
+ case DBG_END_LOCAL: {
+ uint16_t reg = DecodeUnsignedLeb128(&stream);
+ if (reg >= code_item->registers_size_) {
+ LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
+ << code_item->registers_size_ << ") in " << GetLocation();
+ return false;
+ }
+ if (!local_in_reg[reg].is_live_) {
+ LOG(ERROR) << "invalid stream - end without start in " << GetLocation();
+ return false;
+ }
+ local_in_reg[reg].end_address_ = address;
+ local_cb(context, local_in_reg[reg]);
+ local_in_reg[reg].is_live_ = false;
+ break;
+ }
+ case DBG_RESTART_LOCAL: {
+ uint16_t reg = DecodeUnsignedLeb128(&stream);
+ if (reg >= code_item->registers_size_) {
+ LOG(ERROR) << "invalid stream - reg >= reg size (" << reg << " >= "
+ << code_item->registers_size_ << ") in " << GetLocation();
+ return false;
+ }
+ // If the register is live, the "restart" is superfluous,
+ // and we don't want to mess with the existing start address.
+ if (!local_in_reg[reg].is_live_) {
local_in_reg[reg].start_address_ = address;
local_in_reg[reg].is_live_ = true;
}
break;
-
- case DBG_END_LOCAL:
- reg = DecodeUnsignedLeb128(&stream);
- if (reg > code_item->registers_size_) {
- LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
- << code_item->registers_size_ << ") in " << GetLocation();
- return;
- }
-
- if (need_locals) {
- InvokeLocalCbIfLive(context, reg, address, local_in_reg, local_cb);
- local_in_reg[reg].is_live_ = false;
- }
- break;
-
- case DBG_RESTART_LOCAL:
- reg = DecodeUnsignedLeb128(&stream);
- if (reg > code_item->registers_size_) {
- LOG(ERROR) << "invalid stream - reg > reg size (" << reg << " > "
- << code_item->registers_size_ << ") in " << GetLocation();
- return;
- }
-
- if (need_locals) {
- if (local_in_reg[reg].name_ == nullptr || local_in_reg[reg].descriptor_ == nullptr) {
- LOG(ERROR) << "invalid stream - no name or descriptor in " << GetLocation();
- return;
- }
-
- // If the register is live, the "restart" is superfluous,
- // and we don't want to mess with the existing start address.
- if (!local_in_reg[reg].is_live_) {
- local_in_reg[reg].start_address_ = address;
- local_in_reg[reg].is_live_ = true;
- }
- }
- break;
-
+ }
case DBG_SET_PROLOGUE_END:
case DBG_SET_EPILOGUE_BEGIN:
- case DBG_SET_FILE:
break;
+ case DBG_SET_FILE:
+ DecodeUnsignedLeb128P1(&stream); // name.
+ break;
+ default:
+ address += (opcode - DBG_FIRST_SPECIAL) / DBG_LINE_RANGE;
+ break;
+ }
+ }
+}
+bool DexFile::DecodeDebugPositionInfo(const CodeItem* code_item, DexDebugNewPositionCb position_cb,
+ void* context) const {
+ DCHECK(position_cb != nullptr);
+ if (code_item == nullptr) {
+ return false;
+ }
+ const uint8_t* stream = GetDebugInfoStream(code_item);
+ if (stream == nullptr) {
+ return false;
+ }
+
+ PositionInfo entry = PositionInfo();
+ entry.line_ = DecodeUnsignedLeb128(&stream);
+ uint32_t parameters_size = DecodeUnsignedLeb128(&stream);
+ for (uint32_t i = 0; i < parameters_size; ++i) {
+ DecodeUnsignedLeb128P1(&stream); // Parameter name.
+ }
+
+ for (;;) {
+ uint8_t opcode = *stream++;
+ switch (opcode) {
+ case DBG_END_SEQUENCE:
+ return true; // end of stream.
+ case DBG_ADVANCE_PC:
+ entry.address_ += DecodeUnsignedLeb128(&stream);
+ break;
+ case DBG_ADVANCE_LINE:
+ entry.line_ += DecodeSignedLeb128(&stream);
+ break;
+ case DBG_START_LOCAL:
+ DecodeUnsignedLeb128(&stream); // reg.
+ DecodeUnsignedLeb128P1(&stream); // name.
+ DecodeUnsignedLeb128P1(&stream); // descriptor.
+ break;
+ case DBG_START_LOCAL_EXTENDED:
+ DecodeUnsignedLeb128(&stream); // reg.
+ DecodeUnsignedLeb128P1(&stream); // name.
+ DecodeUnsignedLeb128P1(&stream); // descriptor.
+ DecodeUnsignedLeb128P1(&stream); // signature.
+ break;
+ case DBG_END_LOCAL:
+ case DBG_RESTART_LOCAL:
+ DecodeUnsignedLeb128(&stream); // reg.
+ break;
+ case DBG_SET_PROLOGUE_END:
+ entry.prologue_end_ = true;
+ break;
+ case DBG_SET_EPILOGUE_BEGIN:
+ entry.epilogue_begin_ = true;
+ break;
+ case DBG_SET_FILE: {
+ uint32_t name_idx = DecodeUnsignedLeb128P1(&stream);
+ entry.source_file_ = StringDataByIdx(name_idx);
+ break;
+ }
default: {
int adjopcode = opcode - DBG_FIRST_SPECIAL;
-
- address += adjopcode / DBG_LINE_RANGE;
- line += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
-
- if (position_cb != nullptr) {
- if (position_cb(context, address, line)) {
- // early exit
- return;
- }
+ entry.address_ += adjopcode / DBG_LINE_RANGE;
+ entry.line_ += DBG_LINE_BASE + (adjopcode % DBG_LINE_RANGE);
+ if (position_cb(context, entry)) {
+ return true; // early exit.
}
+ entry.prologue_end_ = false;
+ entry.epilogue_begin_ = false;
break;
}
}
}
}
-void DexFile::DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
- DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
- void* context) const {
- DCHECK(code_item != nullptr);
- const uint8_t* stream = GetDebugInfoStream(code_item);
- std::unique_ptr<LocalInfo[]> local_in_reg(local_cb != nullptr ?
- new LocalInfo[code_item->registers_size_] :
- nullptr);
- if (stream != nullptr) {
- DecodeDebugInfo0(code_item, is_static, method_idx, position_cb, local_cb, context, stream,
- &local_in_reg[0]);
- }
- for (int reg = 0; reg < code_item->registers_size_; reg++) {
- InvokeLocalCbIfLive(context, reg, code_item->insns_size_in_code_units_, &local_in_reg[0],
- local_cb);
- }
-}
-
-bool DexFile::LineNumForPcCb(void* raw_context, uint32_t address, uint32_t line_num) {
+bool DexFile::LineNumForPcCb(void* raw_context, const PositionInfo& entry) {
LineNumFromPcContext* context = reinterpret_cast<LineNumFromPcContext*>(raw_context);
// We know that this callback will be called in
// ascending address order, so keep going until we find
// a match or we've just gone past it.
- if (address > context->address_) {
+ if (entry.address_ > context->address_) {
// The line number from the previous positions callback
// wil be the final result.
return true;
} else {
- context->line_num_ = line_num;
- return address == context->address_;
+ context->line_num_ = entry.line_;
+ return entry.address_ == context->address_;
}
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 1e44f50..a9f1e8d 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -819,20 +819,50 @@
}
}
+ struct PositionInfo {
+ PositionInfo()
+ : address_(0),
+ line_(0),
+ source_file_(nullptr),
+ prologue_end_(false),
+ epilogue_begin_(false) {
+ }
+
+ uint32_t address_; // In 16-bit code units.
+ uint32_t line_; // Source code line number starting at 1.
+ const char* source_file_; // nullptr if the file from ClassDef still applies.
+ bool prologue_end_;
+ bool epilogue_begin_;
+ };
+
// Callback for "new position table entry".
// Returning true causes the decoder to stop early.
- typedef bool (*DexDebugNewPositionCb)(void* context, uint32_t address, uint32_t line_num);
+ typedef bool (*DexDebugNewPositionCb)(void* context, const PositionInfo& entry);
- // Callback for "new locals table entry". "signature" is an empty string
- // if no signature is available for an entry.
- typedef void (*DexDebugNewLocalCb)(void* context, uint16_t reg,
- uint32_t start_address,
- uint32_t end_address,
- const char* name,
- const char* descriptor,
- const char* signature);
+ struct LocalInfo {
+ LocalInfo()
+ : name_(nullptr),
+ descriptor_(nullptr),
+ signature_(nullptr),
+ start_address_(0),
+ end_address_(0),
+ reg_(0),
+ is_live_(false) {
+ }
- static bool LineNumForPcCb(void* context, uint32_t address, uint32_t line_num);
+ const char* name_; // E.g., list. It can be nullptr if unknown.
+ const char* descriptor_; // E.g., Ljava/util/LinkedList;
+ const char* signature_; // E.g., java.util.LinkedList<java.lang.Integer>
+ uint32_t start_address_; // PC location where the local is first defined.
+ uint32_t end_address_; // PC location where the local is no longer defined.
+ uint16_t reg_; // Dex register which stores the values.
+ bool is_live_; // Is the local defined and live.
+ };
+
+ // Callback for "new locals table entry".
+ typedef void (*DexDebugNewLocalCb)(void* context, const LocalInfo& entry);
+
+ static bool LineNumForPcCb(void* context, const PositionInfo& entry);
const AnnotationsDirectoryItem* GetAnnotationsDirectory(const ClassDef& class_def) const {
if (class_def.annotations_off_ == 0) {
@@ -1044,21 +1074,6 @@
DBG_LINE_RANGE = 15,
};
- struct LocalInfo {
- LocalInfo()
- : name_(nullptr), descriptor_(nullptr), signature_(nullptr), start_address_(0),
- is_live_(false) {}
-
- const char* name_; // E.g., list
- const char* descriptor_; // E.g., Ljava/util/LinkedList;
- const char* signature_; // E.g., java.util.LinkedList<java.lang.Integer>
- uint16_t start_address_; // PC location where the local is first defined.
- bool is_live_; // Is the local defined and live.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LocalInfo);
- };
-
struct LineNumFromPcContext {
LineNumFromPcContext(uint32_t address, uint32_t line_num)
: address_(address), line_num_(line_num) {}
@@ -1068,15 +1083,6 @@
DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext);
};
- void InvokeLocalCbIfLive(void* context, int reg, uint32_t end_address,
- LocalInfo* local_in_reg, DexDebugNewLocalCb local_cb) const {
- if (local_cb != nullptr && local_in_reg[reg].is_live_) {
- local_cb(context, reg, local_in_reg[reg].start_address_, end_address,
- local_in_reg[reg].name_, local_in_reg[reg].descriptor_,
- local_in_reg[reg].signature_ != nullptr ? local_in_reg[reg].signature_ : "");
- }
- }
-
// Determine the source file line number based on the program counter.
// "pc" is an offset, in 16-bit units, from the start of the method's code.
//
@@ -1088,9 +1094,13 @@
int32_t GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const
SHARED_REQUIRES(Locks::mutator_lock_);
- void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
- DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
- void* context) const;
+ // Returns false if there is no debugging information or if it can not be decoded.
+ bool DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
+ DexDebugNewLocalCb local_cb, void* context) const;
+
+ // Returns false if there is no debugging information or if it can not be decoded.
+ bool DecodeDebugPositionInfo(const CodeItem* code_item, DexDebugNewPositionCb position_cb,
+ void* context) const;
const char* GetSourceFile(const ClassDef& class_def) const {
if (class_def.source_file_idx_ == 0xffffffff) {
@@ -1200,10 +1210,6 @@
// Returns true if the header magic and version numbers are of the expected values.
bool CheckMagicAndVersion(std::string* error_msg) const;
- void DecodeDebugInfo0(const CodeItem* code_item, bool is_static, uint32_t method_idx,
- DexDebugNewPositionCb position_cb, DexDebugNewLocalCb local_cb,
- void* context, const uint8_t* stream, LocalInfo* local_in_reg) const;
-
// Check whether a location denotes a multidex dex file. This is a very simple check: returns
// whether the string contains the separator character.
static bool IsMultiDexLocation(const char* location);
@@ -1275,6 +1281,7 @@
}
}
bool HasNext() const { return pos_ < size_; }
+ size_t Size() const { return size_; }
void Next() { ++pos_; }
uint16_t GetTypeIdx() {
return type_list_->GetTypeItem(pos_).type_idx_;
diff --git a/runtime/jdwp/jdwp_expand_buf.cc b/runtime/jdwp/jdwp_expand_buf.cc
index e492d7e..961dd36 100644
--- a/runtime/jdwp/jdwp_expand_buf.cc
+++ b/runtime/jdwp/jdwp_expand_buf.cc
@@ -164,7 +164,7 @@
* have stored null bytes in a multi-byte encoding).
*/
void expandBufAddUtf8String(ExpandBuf* pBuf, const char* s) {
- int strLen = strlen(s);
+ int strLen = (s != nullptr ? strlen(s) : 0);
ensureSpace(pBuf, sizeof(uint32_t) + strLen);
SetUtf8String(pBuf->storage + pBuf->curLen, s, strLen);
pBuf->curLen += sizeof(uint32_t) + strLen;