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_form_tls_address = 0x9b,
|
||||||
DW_OP_call_frame_cfa = 0x9c,
|
DW_OP_call_frame_cfa = 0x9c,
|
||||||
DW_OP_bit_piece = 0x9d,
|
DW_OP_bit_piece = 0x9d,
|
||||||
|
DW_OP_implicit_value = 0x9e,
|
||||||
|
DW_OP_stack_value = 0x9f,
|
||||||
DW_OP_lo_user = 0xe0,
|
DW_OP_lo_user = 0xe0,
|
||||||
DW_OP_hi_user = 0xff
|
DW_OP_hi_user = 0xff
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2013, Rene Gollent, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -631,6 +632,36 @@ DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
|||||||
TRACE_EXPR(" DW_OP_nop\n");
|
TRACE_EXPR(" DW_OP_nop\n");
|
||||||
break;
|
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:
|
default:
|
||||||
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
||||||
TRACE_EXPR(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
TRACE_EXPR(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2013, Rene Gollent, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -258,6 +259,11 @@ ValueLocation::Dump() const
|
|||||||
case VALUE_PIECE_LOCATION_REGISTER:
|
case VALUE_PIECE_LOCATION_REGISTER:
|
||||||
printf(" register %" B_PRIu32, piece.reg);
|
printf(" register %" B_PRIu32, piece.reg);
|
||||||
break;
|
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
|
printf(" size: %" B_PRIu64 " (%" B_PRIu64 " bits), offset: %" B_PRIu64
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2013, Rene Gollent, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef VALUE_LOCATION_H
|
#ifndef VALUE_LOCATION_H
|
||||||
@@ -16,7 +17,8 @@ enum value_piece_location_type {
|
|||||||
VALUE_PIECE_LOCATION_INVALID, // structure is invalid
|
VALUE_PIECE_LOCATION_INVALID, // structure is invalid
|
||||||
VALUE_PIECE_LOCATION_UNKNOWN, // location unknown, but size is valid
|
VALUE_PIECE_LOCATION_UNKNOWN, // location unknown, but size is valid
|
||||||
VALUE_PIECE_LOCATION_MEMORY, // piece is in memory
|
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
|
uint64 bitOffset; // bit offset (to the most
|
||||||
// significant bit)
|
// significant bit)
|
||||||
value_piece_location_type type;
|
value_piece_location_type type;
|
||||||
|
void* value; // used for storing implicit values
|
||||||
|
|
||||||
|
|
||||||
ValuePieceLocation()
|
ValuePieceLocation()
|
||||||
:
|
:
|
||||||
type(VALUE_PIECE_LOCATION_INVALID)
|
type(VALUE_PIECE_LOCATION_INVALID),
|
||||||
|
value(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ValuePieceLocation()
|
||||||
|
{
|
||||||
|
if (value != NULL)
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValid() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
return type != VALUE_PIECE_LOCATION_INVALID;
|
return type != VALUE_PIECE_LOCATION_INVALID;
|
||||||
@@ -74,6 +85,18 @@ struct ValuePieceLocation {
|
|||||||
this->bitOffset = bitOffset;
|
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);
|
ValuePieceLocation& Normalize(bool bigEndian);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
case VALUE_PIECE_LOCATION_MEMORY:
|
case VALUE_PIECE_LOCATION_MEMORY:
|
||||||
case VALUE_PIECE_LOCATION_REGISTER:
|
case VALUE_PIECE_LOCATION_REGISTER:
|
||||||
|
case VALUE_PIECE_LOCATION_IMPLICIT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,15 +134,29 @@ ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
|
|||||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
case VALUE_PIECE_LOCATION_MEMORY:
|
case VALUE_PIECE_LOCATION_MEMORY:
|
||||||
|
case VALUE_PIECE_LOCATION_IMPLICIT:
|
||||||
{
|
{
|
||||||
target_addr_t address = piece.address;
|
target_addr_t address = piece.address;
|
||||||
|
|
||||||
TRACE_LOCALS(" piece %" B_PRId32 ": memory address: %#"
|
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||||
B_PRIx64 ", bits: %" B_PRIu32 "\n", i, address, bitSize);
|
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];
|
uint8 pieceBuffer[kMaxPieceSize];
|
||||||
ssize_t bytesRead = fTeamMemory->ReadMemory(address,
|
ssize_t bytesRead;
|
||||||
pieceBuffer, bytesToRead);
|
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)
|
if (bytesRead < 0)
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
if ((uint32)bytesRead != bytesToRead)
|
if ((uint32)bytesRead != bytesToRead)
|
||||||
|
|||||||
Reference in New Issue
Block a user