Debugger: Fix #10334.
- In the case of DWARF4's DW_OP_implicit_value, respective handling in Value{Piece}Location wasn't entirely correct, which would lead to double frees in various cases, in particular when copying such objects on the stack. As such, introduce an explicit Copy() member to handle replicating the stored implicit data to avoid that issue. Furthermore, the use of Array<> in ValueLocation wasn't really suitable anymore since ValuePieceLocation now needs its constructor/destructor to be executed, while Array is intended for POD types; consequently, replace that with std::vector and adjust handling code accordingly.
This commit is contained in:
parent
5e815cf35b
commit
729dc43722
@ -306,7 +306,10 @@ DwarfType::ResolveObjectDataLocation(const ValueLocation& objectLocation,
|
||||
if (count == 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ValuePieceLocation piece = objectLocation.PieceAt(0);
|
||||
ValuePieceLocation piece;
|
||||
if (!piece.Copy(objectLocation.PieceAt(0)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (count > 1 || piece.type != VALUE_PIECE_LOCATION_MEMORY
|
||||
|| piece.size != 0 || piece.bitSize != 0) {
|
||||
ValueLocation* location
|
||||
@ -376,7 +379,10 @@ DwarfType::ResolveLocation(DwarfTypeContext* typeContext,
|
||||
bool bigEndian = typeContext->GetArchitecture()->IsBigEndian();
|
||||
int32 count = _location.CountPieces();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = _location.PieceAt(i);
|
||||
ValuePieceLocation piece;
|
||||
if (!piece.Copy(_location.PieceAt(i)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (piece.type == VALUE_PIECE_LOCATION_REGISTER) {
|
||||
int32 reg = typeContext->FromDwarfRegisterMap()->MapRegisterIndex(
|
||||
piece.reg);
|
||||
@ -403,17 +409,22 @@ DwarfType::ResolveLocation(DwarfTypeContext* typeContext,
|
||||
}
|
||||
|
||||
piece.Normalize(bigEndian);
|
||||
_location.SetPieceAt(i, piece);
|
||||
if (!_location.SetPieceAt(i, piece))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// If we only have one piece and that doesn't have a size, try to retrieve
|
||||
// the size of the type.
|
||||
if (count == 1) {
|
||||
ValuePieceLocation piece = _location.PieceAt(0);
|
||||
ValuePieceLocation piece;
|
||||
if (!piece.Copy(_location.PieceAt(0)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (piece.IsValid() && piece.size == 0 && piece.bitSize == 0) {
|
||||
piece.SetSize(ByteSize());
|
||||
// TODO: Use bit size and bit offset, if specified!
|
||||
_location.SetPieceAt(0, piece);
|
||||
if (!_location.SetPieceAt(0, piece))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
TRACE_LOCALS(" set single piece size to %" B_PRIu64 "\n",
|
||||
ByteSize());
|
||||
@ -904,7 +915,8 @@ DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
|
||||
// location to be a memory location.
|
||||
if (parentLocation.CountPieces() != 1)
|
||||
return B_BAD_VALUE;
|
||||
ValuePieceLocation piece = parentLocation.PieceAt(0);
|
||||
const ValuePieceLocation& piece = parentLocation.PieceAt(0);
|
||||
|
||||
if (piece.type != VALUE_PIECE_LOCATION_MEMORY)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
@ -938,7 +950,10 @@ DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
|
||||
// the location by hand since we don't want the size difference
|
||||
// between the overall union and the member being
|
||||
// factored into the assigned address.
|
||||
ValuePieceLocation piece = parentLocation.PieceAt(0);
|
||||
ValuePieceLocation piece;
|
||||
if (!piece.Copy(parentLocation.PieceAt(0)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
piece.SetSize(memberType->ByteSize());
|
||||
if (!location->AddPiece(piece))
|
||||
return B_NO_MEMORY;
|
||||
@ -1123,7 +1138,10 @@ DwarfArrayType::ResolveElementLocation(const ArrayIndexPath& indexPath,
|
||||
// If we have a single memory piece location for the array, we compute the
|
||||
// element's location by hand -- not uncommonly the array size isn't known.
|
||||
if (parentLocation.CountPieces() == 1) {
|
||||
ValuePieceLocation piece = parentLocation.PieceAt(0);
|
||||
ValuePieceLocation piece;
|
||||
if (!piece.Copy(parentLocation.PieceAt(0)))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||
int64 byteOffset = elementOffset >= 0
|
||||
? elementOffset / 8 : (elementOffset - 7) / 8;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ValueLocation.h"
|
||||
|
||||
@ -101,7 +102,7 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
int32 count = other.CountPieces();
|
||||
uint64 totalBitSize = 0;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = other.PieceAt(i);
|
||||
const ValuePieceLocation &piece = other.PieceAt(i);
|
||||
totalBitSize += piece.bitSize;
|
||||
}
|
||||
|
||||
@ -122,10 +123,13 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
int32 i;
|
||||
ValuePieceLocation piece;
|
||||
for (i = 0; i < count; i++) {
|
||||
piece = other.PieceAt(i);
|
||||
if (piece.bitSize > bitsToSkip)
|
||||
const ValuePieceLocation& tempPiece = other.PieceAt(i);
|
||||
if (tempPiece.bitSize > bitsToSkip) {
|
||||
if (!piece.Copy(tempPiece))
|
||||
return false;
|
||||
break;
|
||||
bitsToSkip -= piece.bitSize;
|
||||
}
|
||||
bitsToSkip -= tempPiece.bitSize;
|
||||
}
|
||||
|
||||
// handle partial piece
|
||||
@ -151,7 +155,8 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
if (++i >= count)
|
||||
break;
|
||||
|
||||
piece = other.PieceAt(i);
|
||||
if (!piece.Copy(other.PieceAt(i)))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Little endian: Skip the superfluous least significant bits, copy the
|
||||
@ -163,9 +168,12 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
int32 i;
|
||||
ValuePieceLocation piece;
|
||||
for (i = 0; i < count; i++) {
|
||||
piece = other.PieceAt(i);
|
||||
if (piece.bitSize > bitsToSkip)
|
||||
const ValuePieceLocation& tempPiece = other.PieceAt(i);
|
||||
if (tempPiece.bitSize > bitsToSkip) {
|
||||
if (!piece.Copy(tempPiece))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
bitsToSkip -= piece.bitSize;
|
||||
}
|
||||
|
||||
@ -192,7 +200,8 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
if (++i >= count)
|
||||
break;
|
||||
|
||||
piece = other.PieceAt(i);
|
||||
if (!piece.Copy(other.PieceAt(i)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,7 +212,7 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
|
||||
void
|
||||
ValueLocation::Clear()
|
||||
{
|
||||
fPieces.Clear();
|
||||
fPieces.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -212,34 +221,40 @@ ValueLocation::AddPiece(const ValuePieceLocation& piece)
|
||||
{
|
||||
// Just add, don't normalize. This allows for using the class with different
|
||||
// semantics (e.g. in the DWARF code).
|
||||
return fPieces.Add(piece);
|
||||
try {
|
||||
fPieces.push_back(piece);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ValueLocation::CountPieces() const
|
||||
{
|
||||
return fPieces.Size();
|
||||
return fPieces.size();
|
||||
}
|
||||
|
||||
|
||||
ValuePieceLocation
|
||||
ValueLocation::PieceAt(int32 index) const
|
||||
{
|
||||
if (index < 0 || index >= fPieces.Size())
|
||||
if (index < 0 || index >= (int32)fPieces.size())
|
||||
return ValuePieceLocation();
|
||||
|
||||
return fPieces.ElementAt(index);
|
||||
return fPieces[index];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
ValueLocation::SetPieceAt(int32 index, const ValuePieceLocation& piece)
|
||||
{
|
||||
if (index < 0 || index >= fPieces.Size())
|
||||
return;
|
||||
if (index < 0 || index >= (int32)fPieces.size())
|
||||
return false;
|
||||
|
||||
fPieces.ElementAt(index) = piece;
|
||||
return fPieces[index].Copy(piece);
|
||||
}
|
||||
|
||||
|
||||
@ -255,7 +270,7 @@ ValueLocation::operator=(const ValueLocation& other)
|
||||
void
|
||||
ValueLocation::Dump() const
|
||||
{
|
||||
int32 count = fPieces.Size();
|
||||
int32 count = fPieces.size();
|
||||
printf("ValueLocation: %s endian, %" B_PRId32 " pieces:\n",
|
||||
fBigEndian ? "big" : "little", count);
|
||||
|
||||
|
@ -6,8 +6,11 @@
|
||||
#ifndef VALUE_LOCATION_H
|
||||
#define VALUE_LOCATION_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Array.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "Types.h"
|
||||
@ -43,12 +46,43 @@ struct ValuePieceLocation {
|
||||
{
|
||||
}
|
||||
|
||||
ValuePieceLocation(const ValuePieceLocation& other)
|
||||
{
|
||||
if (!Copy(other))
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
~ValuePieceLocation()
|
||||
{
|
||||
if (value != NULL)
|
||||
free(value);
|
||||
}
|
||||
|
||||
ValuePieceLocation& operator=(const ValuePieceLocation& other)
|
||||
{
|
||||
if (!Copy(other))
|
||||
throw std::bad_alloc();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Copy(const ValuePieceLocation& other)
|
||||
{
|
||||
memcpy(this, &other, sizeof(ValuePieceLocation));
|
||||
if (type == VALUE_PIECE_LOCATION_IMPLICIT) {
|
||||
void* tempValue = malloc(size);
|
||||
if (tempValue == NULL) {
|
||||
type = VALUE_PIECE_LOCATION_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(tempValue, value, other.size);
|
||||
value = tempValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return type != VALUE_PIECE_LOCATION_INVALID;
|
||||
@ -107,6 +141,7 @@ public:
|
||||
ValueLocation(bool bigEndian);
|
||||
ValueLocation(bool bigEndian,
|
||||
const ValuePieceLocation& piece);
|
||||
|
||||
ValueLocation(const ValueLocation& other);
|
||||
|
||||
bool SetToByteOffset(const ValueLocation& other,
|
||||
@ -123,18 +158,17 @@ public:
|
||||
|
||||
int32 CountPieces() const;
|
||||
ValuePieceLocation PieceAt(int32 index) const;
|
||||
void SetPieceAt(int32 index,
|
||||
bool SetPieceAt(int32 index,
|
||||
const ValuePieceLocation& piece);
|
||||
|
||||
ValueLocation& operator=(const ValueLocation& other);
|
||||
|
||||
void Dump() const;
|
||||
|
||||
private:
|
||||
typedef Array<ValuePieceLocation> PieceArray;
|
||||
typedef std::vector<ValuePieceLocation> PieceVector;
|
||||
|
||||
private:
|
||||
PieceArray fPieces;
|
||||
PieceVector fPieces;
|
||||
bool fBigEndian;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user