@@ -861,84 +861,146 @@ ResolveLoadAddress(ExecutionContext *exe_ctx, lldb::ModuleSP &module_sp,
861861 return load_addr;
862862}
863863
864- static llvm::Error Evaluate_DW_OP_deref (DWARFExpression::Stack &stack,
865- ExecutionContext *exe_ctx,
866- lldb::ModuleSP module_sp,
867- Process *process) {
864+ // / @brief Helper function to load sized data from a uint8_t buffer.
865+ // /
866+ // / @param addr_bytes The buffer containing raw data.
867+ // / @param size_addr_bytes How large is the underlying raw data.
868+ // / @param byte_order What is the byte order of the underlying data.
869+ // / @param size How much of the underlying data we want to use.
870+ // / @return The underlying data converted into a Scalar.
871+ static Scalar DerefSizeExtractDataHelper (uint8_t *addr_bytes,
872+ size_t size_addr_bytes,
873+ ByteOrder byte_order, size_t size) {
874+ DataExtractor addr_data (addr_bytes, size_addr_bytes, byte_order, size);
875+
876+ lldb::offset_t addr_data_offset = 0 ;
877+ if (size <= 8 )
878+ return addr_data.GetMaxU64 (&addr_data_offset, size);
879+ return addr_data.GetAddress (&addr_data_offset);
880+ }
881+
882+ static llvm::Error Evaluate_DW_OP_deref_size (DWARFExpression::Stack &stack,
883+ ExecutionContext *exe_ctx,
884+ lldb::ModuleSP module_sp,
885+ Process *process, Target *target,
886+ uint8_t size) {
868887 if (stack.empty ())
869- return llvm::createStringError (" expression stack empty for DW_OP_deref" );
888+ return llvm::createStringError (
889+ " expression stack empty for DW_OP_deref_size" );
870890
871- const Value::ValueType value_type = stack.back ().GetValueType ();
891+ if (size > 8 )
892+ return llvm::createStringError (
893+ " Invalid address size for DW_OP_deref_size: %d\n " , size);
894+
895+ Value::ValueType value_type = stack.back ().GetValueType ();
872896 switch (value_type) {
873897 case Value::ValueType::HostAddress: {
874898 void *src = (void *)stack.back ().GetScalar ().ULongLong ();
875899 intptr_t ptr;
876900 ::memcpy (&ptr, src, sizeof (void *));
901+ // I can't decide whether the size operand should apply to the bytes in
902+ // their lldb-host endianness or the target endianness.. I doubt this'll
903+ // ever come up but I'll opt for assuming big endian regardless.
904+ switch (size) {
905+ case 1 :
906+ ptr = ptr & 0xff ;
907+ break ;
908+ case 2 :
909+ ptr = ptr & 0xffff ;
910+ break ;
911+ case 3 :
912+ ptr = ptr & 0xffffff ;
913+ break ;
914+ case 4 :
915+ ptr = ptr & 0xffffffff ;
916+ break ;
917+ // The casts are added to work around the case where intptr_t is a 32-bit
918+ // quantity. Presumably we won't hit the 5..7 cases if (void*) is 32-bits in
919+ // this program.
920+ case 5 :
921+ ptr = (intptr_t )ptr & 0xffffffffffULL ;
922+ break ;
923+ case 6 :
924+ ptr = (intptr_t )ptr & 0xffffffffffffULL ;
925+ break ;
926+ case 7 :
927+ ptr = (intptr_t )ptr & 0xffffffffffffffULL ;
928+ break ;
929+ default :
930+ break ;
931+ }
877932 stack.back ().GetScalar () = ptr;
878933 stack.back ().ClearContext ();
879934 } break ;
880935 case Value::ValueType::FileAddress: {
881936 auto file_addr = stack.back ().GetScalar ().ULongLong (LLDB_INVALID_ADDRESS);
882937 Address so_addr;
883- auto maybe_load_addr = ResolveLoadAddress (exe_ctx, module_sp, " DW_OP_deref" ,
884- file_addr, so_addr);
938+ auto maybe_load_addr = ResolveLoadAddress (
939+ exe_ctx, module_sp, " DW_OP_deref_size" , file_addr, so_addr,
940+ /* check_sectionoffset=*/ true );
941+
885942 if (!maybe_load_addr)
886943 return maybe_load_addr.takeError ();
887- stack.back ().GetScalar () = *maybe_load_addr;
944+
945+ addr_t load_addr = *maybe_load_addr;
946+
947+ if (load_addr == LLDB_INVALID_ADDRESS && so_addr.IsSectionOffset ()) {
948+ uint8_t addr_bytes[8 ];
949+ Status error;
950+
951+ if (!target || target->ReadMemory (so_addr, &addr_bytes, size, error,
952+ /* force_live_memory=*/ false ) != size)
953+ return llvm::createStringError (
954+ " failed to dereference pointer for DW_OP_deref_size: "
955+ " %s\n " ,
956+ error.AsCString ());
957+
958+ ObjectFile *objfile = module_sp->GetObjectFile ();
959+
960+ stack.back ().GetScalar () = DerefSizeExtractDataHelper (
961+ addr_bytes, size, objfile->GetByteOrder (), size);
962+ stack.back ().ClearContext ();
963+ break ;
964+ }
965+ stack.back ().GetScalar () = load_addr;
888966 // Fall through to load address promotion code below.
889967 }
968+
890969 [[fallthrough]];
891970 case Value::ValueType::Scalar:
892971 // Promote Scalar to LoadAddress and fall through.
893972 stack.back ().SetValueType (Value::ValueType::LoadAddress);
894973 [[fallthrough]];
895974 case Value::ValueType::LoadAddress: {
896975 if (!exe_ctx)
897- return llvm::createStringError (" NULL execution context for DW_OP_deref" );
976+ return llvm::createStringError (
977+ " no execution context for DW_OP_deref_size" );
898978 if (!process)
899- return llvm::createStringError (" NULL process for DW_OP_deref" );
979+ return llvm::createStringError (" no process for DW_OP_deref_size" );
980+
900981 lldb::addr_t pointer_addr =
901982 stack.back ().GetScalar ().ULongLong (LLDB_INVALID_ADDRESS);
983+ uint8_t addr_bytes[sizeof (lldb::addr_t )];
902984 Status error;
903- lldb::addr_t pointer_value =
904- process->ReadPointerFromMemory (pointer_addr, error);
905- if (pointer_value == LLDB_INVALID_ADDRESS)
906- return llvm::joinErrors (
907- llvm::createStringError (
908- " Failed to dereference pointer from 0x%" PRIx64
909- " for DW_OP_deref" ,
910- pointer_addr),
911- error.takeError ());
912- stack.back ().GetScalar () = pointer_value;
985+
986+ if (process->ReadMemory (pointer_addr, &addr_bytes, size, error) != size)
987+ return llvm::createStringError (
988+ " failed to dereference pointer from 0x%" PRIx64
989+ " for DW_OP_deref_size: %s\n " ,
990+ pointer_addr, error.AsCString ());
991+
992+ stack.back ().GetScalar () = DerefSizeExtractDataHelper (
993+ addr_bytes, sizeof (addr_bytes), process->GetByteOrder (), size);
913994 stack.back ().ClearContext ();
914995 } break ;
996+
915997 case Value::ValueType::Invalid:
916- return llvm::createStringError (" invalid value type for DW_OP_deref " );
998+ return llvm::createStringError (" invalid value for DW_OP_deref_size " );
917999 }
9181000
9191001 return llvm::Error::success ();
9201002}
9211003
922- // / Helper function to move common code used to load sized data from a uint8_t
923- // / buffer.
924- // /
925- // / \param addr_bytes uint8_t buffer containg raw data
926- // / \param size_addr_bytes how large is the underlying raw data
927- // / \param byte_order what is the byter order of the underlyig data
928- // / \param size How much of the underlying data we want to use
929- // / \return The underlying data converted into a Scalar
930- static Scalar DerefSizeExtractDataHelper (uint8_t *addr_bytes,
931- size_t size_addr_bytes,
932- ByteOrder byte_order, size_t size) {
933- DataExtractor addr_data (addr_bytes, size_addr_bytes, byte_order, size);
934-
935- lldb::offset_t addr_data_offset = 0 ;
936- if (size <= 8 )
937- return addr_data.GetMaxU64 (&addr_data_offset, size);
938- else
939- return addr_data.GetAddress (&addr_data_offset);
940- }
941-
9421004llvm::Expected<Value> DWARFExpression::Evaluate (
9431005 ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
9441006 lldb::ModuleSP module_sp, const DataExtractor &opcodes,
@@ -1079,8 +1141,9 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
10791141 // retrieved from the dereferenced address is the size of an address on the
10801142 // target machine.
10811143 case DW_OP_deref: {
1082- if (llvm::Error err =
1083- Evaluate_DW_OP_deref (stack, exe_ctx, module_sp, process))
1144+ size_t size = opcodes.GetAddressByteSize ();
1145+ if (llvm::Error err = Evaluate_DW_OP_deref_size (stack, exe_ctx, module_sp,
1146+ process, target, size))
10841147 return err;
10851148 } break ;
10861149
@@ -1097,131 +1160,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
10971160 // the size of an address on the target machine before being pushed on the
10981161 // expression stack.
10991162 case DW_OP_deref_size: {
1100- if (stack.empty ()) {
1101- return llvm::createStringError (
1102- " expression stack empty for DW_OP_deref_size" );
1103- }
1104- uint8_t size = opcodes.GetU8 (&offset);
1105- if (size > 8 ) {
1106- return llvm::createStringError (
1107- " Invalid address size for DW_OP_deref_size: %d\n " , size);
1108- }
1109- Value::ValueType value_type = stack.back ().GetValueType ();
1110- switch (value_type) {
1111- case Value::ValueType::HostAddress: {
1112- void *src = (void *)stack.back ().GetScalar ().ULongLong ();
1113- intptr_t ptr;
1114- ::memcpy (&ptr, src, sizeof (void *));
1115- // I can't decide whether the size operand should apply to the bytes in
1116- // their
1117- // lldb-host endianness or the target endianness.. I doubt this'll ever
1118- // come up but I'll opt for assuming big endian regardless.
1119- switch (size) {
1120- case 1 :
1121- ptr = ptr & 0xff ;
1122- break ;
1123- case 2 :
1124- ptr = ptr & 0xffff ;
1125- break ;
1126- case 3 :
1127- ptr = ptr & 0xffffff ;
1128- break ;
1129- case 4 :
1130- ptr = ptr & 0xffffffff ;
1131- break ;
1132- // the casts are added to work around the case where intptr_t is a 32
1133- // bit quantity;
1134- // presumably we won't hit the 5..7 cases if (void*) is 32-bits in this
1135- // program.
1136- case 5 :
1137- ptr = (intptr_t )ptr & 0xffffffffffULL ;
1138- break ;
1139- case 6 :
1140- ptr = (intptr_t )ptr & 0xffffffffffffULL ;
1141- break ;
1142- case 7 :
1143- ptr = (intptr_t )ptr & 0xffffffffffffffULL ;
1144- break ;
1145- default :
1146- break ;
1147- }
1148- stack.back ().GetScalar () = ptr;
1149- stack.back ().ClearContext ();
1150- } break ;
1151- case Value::ValueType::FileAddress: {
1152- auto file_addr =
1153- stack.back ().GetScalar ().ULongLong (LLDB_INVALID_ADDRESS);
1154- Address so_addr;
1155- auto maybe_load_addr = ResolveLoadAddress (
1156- exe_ctx, module_sp, " DW_OP_deref_size" , file_addr, so_addr,
1157- /* check_sectionoffset=*/ true );
1158-
1159- if (!maybe_load_addr)
1160- return maybe_load_addr.takeError ();
1161-
1162- addr_t load_addr = *maybe_load_addr;
1163-
1164- if (load_addr == LLDB_INVALID_ADDRESS && so_addr.IsSectionOffset ()) {
1165- uint8_t addr_bytes[8 ];
1166- Status error;
1167-
1168- if (target &&
1169- target->ReadMemory (so_addr, &addr_bytes, size, error,
1170- /* force_live_memory=*/ false ) == size) {
1171- ObjectFile *objfile = module_sp->GetObjectFile ();
1172-
1173- stack.back ().GetScalar () = DerefSizeExtractDataHelper (
1174- addr_bytes, size, objfile->GetByteOrder (), size);
1175- stack.back ().ClearContext ();
1176- break ;
1177- } else {
1178- return llvm::createStringError (
1179- " Failed to dereference pointer for DW_OP_deref_size: "
1180- " %s\n " ,
1181- error.AsCString ());
1182- }
1183- }
1184- stack.back ().GetScalar () = load_addr;
1185- // Fall through to load address promotion code below.
1186- }
1187-
1188- [[fallthrough]];
1189- case Value::ValueType::Scalar:
1190- case Value::ValueType::LoadAddress:
1191- if (exe_ctx) {
1192- if (process) {
1193- lldb::addr_t pointer_addr =
1194- stack.back ().GetScalar ().ULongLong (LLDB_INVALID_ADDRESS);
1195- uint8_t addr_bytes[sizeof (lldb::addr_t )];
1196- Status error;
1197- if (process->ReadMemory (pointer_addr, &addr_bytes, size, error) ==
1198- size) {
1199-
1200- stack.back ().GetScalar () =
1201- DerefSizeExtractDataHelper (addr_bytes, sizeof (addr_bytes),
1202- process->GetByteOrder (), size);
1203- stack.back ().ClearContext ();
1204- } else {
1205- return llvm::createStringError (
1206- " Failed to dereference pointer from 0x%" PRIx64
1207- " for DW_OP_deref: %s\n " ,
1208- pointer_addr, error.AsCString ());
1209- }
1210- } else {
1211-
1212- return llvm::createStringError (" NULL process for DW_OP_deref_size" );
1213- }
1214- } else {
1215- return llvm::createStringError (
1216- " NULL execution context for DW_OP_deref_size" );
1217- }
1218- break ;
1219-
1220- case Value::ValueType::Invalid:
1221-
1222- return llvm::createStringError (" invalid value for DW_OP_deref_size" );
1223- }
1224-
1163+ size_t size = opcodes.GetU8 (&offset);
1164+ if (llvm::Error err = Evaluate_DW_OP_deref_size (stack, exe_ctx, module_sp,
1165+ process, target, size))
1166+ return err;
12251167 } break ;
12261168
12271169 // OPCODE: DW_OP_xderef_size
0 commit comments