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:
Rene Gollent
2013-07-20 23:38:29 -04:00
parent a326afa3fc
commit d950dcd9ab
5 changed files with 83 additions and 6 deletions
+2
View File
@@ -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
+25 -2
View File
@@ -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);
};
+19 -4
View File
@@ -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)