Debugger: Implement new expression operands.
DWARF4 adds two new expression operands for values that are known, but not located anywhere in memory (e.g. a known constant or a value computed from a composite of other values/locations in the program). These are DW_OP_implicit_value, which supplies the value directly as an LEB128 + data block, and DW_OP_stack_value, which indicates the top of the expression stack is the value. Implements corresponding support in DwarfExpressionEvaluator, ValueLocation and ValueLoader.
This commit is contained in:
@@ -306,6 +306,8 @@ enum {
|
||||
DW_OP_form_tls_address = 0x9b,
|
||||
DW_OP_call_frame_cfa = 0x9c,
|
||||
DW_OP_bit_piece = 0x9d,
|
||||
DW_OP_implicit_value = 0x9e,
|
||||
DW_OP_stack_value = 0x9f,
|
||||
DW_OP_lo_user = 0xe0,
|
||||
DW_OP_hi_user = 0xff
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||
* Copyright 2013, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -631,6 +632,36 @@ DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
||||
TRACE_EXPR(" DW_OP_nop\n");
|
||||
break;
|
||||
|
||||
case DW_OP_implicit_value:
|
||||
{
|
||||
TRACE_EXPR(" DW_OP_implicit_value\n");
|
||||
if (_piece == NULL) {
|
||||
throw EvaluationException(
|
||||
"DW_OP_implicit_value in non-location expression");
|
||||
}
|
||||
uint32 length = fDataReader.ReadUnsignedLEB128(0);
|
||||
if (length == 0)
|
||||
return B_BAD_DATA;
|
||||
|
||||
if (fDataReader.BytesRemaining() < length)
|
||||
return B_BAD_DATA;
|
||||
|
||||
_piece->SetToValue(fDataReader.Data(), length);
|
||||
return B_OK;
|
||||
}
|
||||
case DW_OP_stack_value:
|
||||
{
|
||||
TRACE_EXPR(" DW_OP_stack_value\n");
|
||||
if (_piece == NULL) {
|
||||
throw EvaluationException(
|
||||
"DW_OP_stack_value in non-location expression");
|
||||
}
|
||||
if (fStackSize == 0)
|
||||
return B_BAD_DATA;
|
||||
target_addr_t value = _Pop();
|
||||
_piece->SetToValue(&value, sizeof(target_addr_t));
|
||||
return B_OK;
|
||||
}
|
||||
default:
|
||||
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
||||
TRACE_EXPR(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -258,6 +259,11 @@ ValueLocation::Dump() const
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
printf(" register %" B_PRIu32, piece.reg);
|
||||
break;
|
||||
case VALUE_PIECE_LOCATION_IMPLICIT:
|
||||
printf(" implicit value: ");
|
||||
for (uint32 j = 0; j < piece.size; j++)
|
||||
printf("%x ", ((char *)piece.value)[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" size: %" B_PRIu64 " (%" B_PRIu64 " bits), offset: %" B_PRIu64
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_LOCATION_H
|
||||
@@ -16,7 +17,8 @@ enum value_piece_location_type {
|
||||
VALUE_PIECE_LOCATION_INVALID, // structure is invalid
|
||||
VALUE_PIECE_LOCATION_UNKNOWN, // location unknown, but size is valid
|
||||
VALUE_PIECE_LOCATION_MEMORY, // piece is in memory
|
||||
VALUE_PIECE_LOCATION_REGISTER // piece is in a register
|
||||
VALUE_PIECE_LOCATION_REGISTER, // piece is in a register
|
||||
VALUE_PIECE_LOCATION_IMPLICIT // value isn't stored anywhere in memory but is known
|
||||
};
|
||||
|
||||
|
||||
@@ -31,13 +33,22 @@ struct ValuePieceLocation {
|
||||
uint64 bitOffset; // bit offset (to the most
|
||||
// significant bit)
|
||||
value_piece_location_type type;
|
||||
void* value; // used for storing implicit values
|
||||
|
||||
|
||||
ValuePieceLocation()
|
||||
:
|
||||
type(VALUE_PIECE_LOCATION_INVALID)
|
||||
type(VALUE_PIECE_LOCATION_INVALID),
|
||||
value(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~ValuePieceLocation()
|
||||
{
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return type != VALUE_PIECE_LOCATION_INVALID;
|
||||
@@ -74,6 +85,18 @@ struct ValuePieceLocation {
|
||||
this->bitOffset = bitOffset;
|
||||
}
|
||||
|
||||
bool SetToValue(const void* data, target_size_t size)
|
||||
{
|
||||
char* valueData = (char*)malloc(size);
|
||||
if (valueData == NULL)
|
||||
return false;
|
||||
memcpy(valueData, data, size);
|
||||
SetSize(size);
|
||||
type = VALUE_PIECE_LOCATION_IMPLICIT;
|
||||
value = valueData;
|
||||
return true;
|
||||
}
|
||||
|
||||
ValuePieceLocation& Normalize(bool bigEndian);
|
||||
};
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
case VALUE_PIECE_LOCATION_IMPLICIT:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -133,15 +134,29 @@ ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
|
||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
case VALUE_PIECE_LOCATION_IMPLICIT:
|
||||
{
|
||||
target_addr_t address = piece.address;
|
||||
|
||||
TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#"
|
||||
B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address, bitSize);
|
||||
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||
TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#"
|
||||
B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address,
|
||||
bitSize);
|
||||
} else {
|
||||
TRACE_LOCALS(" piece %" B_PRId32 ": implicit value, "
|
||||
"bits: %" B_PRIu32 "\n", i, bitSize);
|
||||
}
|
||||
|
||||
uint8 pieceBuffer[kMaxPieceSize];
|
||||
ssize_t bytesRead = fTeamMemory->ReadMemory(address,
|
||||
pieceBuffer, bytesToRead);
|
||||
ssize_t bytesRead;
|
||||
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||
bytesRead = fTeamMemory->ReadMemory(address,
|
||||
pieceBuffer, bytesToRead);
|
||||
} else {
|
||||
memcpy(pieceBuffer, piece.value, piece.size);
|
||||
bytesRead = piece.size;
|
||||
}
|
||||
|
||||
if (bytesRead < 0)
|
||||
return bytesRead;
|
||||
if ((uint32)bytesRead != bytesToRead)
|
||||
|
||||
Reference in New Issue
Block a user