1cfca06d7SDimitry Andric //===-- DumpDataExtractor.cpp ---------------------------------------------===//
274a628f7SDimitry Andric //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
674a628f7SDimitry Andric //
774a628f7SDimitry Andric //===----------------------------------------------------------------------===//
874a628f7SDimitry Andric
974a628f7SDimitry Andric #include "lldb/Core/DumpDataExtractor.h"
1074a628f7SDimitry Andric
1194994d37SDimitry Andric #include "lldb/lldb-defines.h"
1294994d37SDimitry Andric #include "lldb/lldb-forward.h"
1374a628f7SDimitry Andric
1494994d37SDimitry Andric #include "lldb/Core/Address.h"
1574a628f7SDimitry Andric #include "lldb/Core/Disassembler.h"
1694994d37SDimitry Andric #include "lldb/Core/ModuleList.h"
17344a3780SDimitry Andric #include "lldb/Target/ABI.h"
1874a628f7SDimitry Andric #include "lldb/Target/ExecutionContext.h"
1974a628f7SDimitry Andric #include "lldb/Target/ExecutionContextScope.h"
206f8fc217SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
216f8fc217SDimitry Andric #include "lldb/Target/MemoryTagManager.h"
226f8fc217SDimitry Andric #include "lldb/Target/MemoryTagMap.h"
23344a3780SDimitry Andric #include "lldb/Target/Process.h"
2474a628f7SDimitry Andric #include "lldb/Target/SectionLoadList.h"
2574a628f7SDimitry Andric #include "lldb/Target/Target.h"
2674a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
27ead24645SDimitry Andric #include "lldb/Utility/Log.h"
2874a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
2974a628f7SDimitry Andric
3094994d37SDimitry Andric #include "llvm/ADT/APFloat.h"
3194994d37SDimitry Andric #include "llvm/ADT/APInt.h"
3294994d37SDimitry Andric #include "llvm/ADT/ArrayRef.h"
3394994d37SDimitry Andric #include "llvm/ADT/SmallVector.h"
3474a628f7SDimitry Andric
3594994d37SDimitry Andric #include <limits>
3694994d37SDimitry Andric #include <memory>
3794994d37SDimitry Andric #include <string>
3874a628f7SDimitry Andric
39344a3780SDimitry Andric #include <cassert>
40344a3780SDimitry Andric #include <cctype>
41344a3780SDimitry Andric #include <cinttypes>
42344a3780SDimitry Andric #include <cmath>
4374a628f7SDimitry Andric
4474a628f7SDimitry Andric #include <bitset>
45e3b55780SDimitry Andric #include <optional>
4674a628f7SDimitry Andric #include <sstream>
4774a628f7SDimitry Andric
4874a628f7SDimitry Andric using namespace lldb_private;
4974a628f7SDimitry Andric using namespace lldb;
5074a628f7SDimitry Andric
5174a628f7SDimitry Andric #define NON_PRINTABLE_CHAR '.'
5274a628f7SDimitry Andric
GetAPInt(const DataExtractor & data,lldb::offset_t * offset_ptr,lldb::offset_t byte_size)53e3b55780SDimitry Andric static std::optional<llvm::APInt> GetAPInt(const DataExtractor &data,
54ead24645SDimitry Andric lldb::offset_t *offset_ptr,
55ead24645SDimitry Andric lldb::offset_t byte_size) {
56ead24645SDimitry Andric if (byte_size == 0)
57e3b55780SDimitry Andric return std::nullopt;
58ead24645SDimitry Andric
5974a628f7SDimitry Andric llvm::SmallVector<uint64_t, 2> uint64_array;
6074a628f7SDimitry Andric lldb::offset_t bytes_left = byte_size;
6174a628f7SDimitry Andric uint64_t u64;
6274a628f7SDimitry Andric const lldb::ByteOrder byte_order = data.GetByteOrder();
6374a628f7SDimitry Andric if (byte_order == lldb::eByteOrderLittle) {
6474a628f7SDimitry Andric while (bytes_left > 0) {
6574a628f7SDimitry Andric if (bytes_left >= 8) {
6674a628f7SDimitry Andric u64 = data.GetU64(offset_ptr);
6774a628f7SDimitry Andric bytes_left -= 8;
6874a628f7SDimitry Andric } else {
6974a628f7SDimitry Andric u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
7074a628f7SDimitry Andric bytes_left = 0;
7174a628f7SDimitry Andric }
7274a628f7SDimitry Andric uint64_array.push_back(u64);
7374a628f7SDimitry Andric }
74ead24645SDimitry Andric return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
7574a628f7SDimitry Andric } else if (byte_order == lldb::eByteOrderBig) {
7674a628f7SDimitry Andric lldb::offset_t be_offset = *offset_ptr + byte_size;
7774a628f7SDimitry Andric lldb::offset_t temp_offset;
7874a628f7SDimitry Andric while (bytes_left > 0) {
7974a628f7SDimitry Andric if (bytes_left >= 8) {
8074a628f7SDimitry Andric be_offset -= 8;
8174a628f7SDimitry Andric temp_offset = be_offset;
8274a628f7SDimitry Andric u64 = data.GetU64(&temp_offset);
8374a628f7SDimitry Andric bytes_left -= 8;
8474a628f7SDimitry Andric } else {
8574a628f7SDimitry Andric be_offset -= bytes_left;
8674a628f7SDimitry Andric temp_offset = be_offset;
8774a628f7SDimitry Andric u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
8874a628f7SDimitry Andric bytes_left = 0;
8974a628f7SDimitry Andric }
9074a628f7SDimitry Andric uint64_array.push_back(u64);
9174a628f7SDimitry Andric }
9274a628f7SDimitry Andric *offset_ptr += byte_size;
93ead24645SDimitry Andric return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
9474a628f7SDimitry Andric }
95e3b55780SDimitry Andric return std::nullopt;
9674a628f7SDimitry Andric }
9774a628f7SDimitry Andric
DumpAPInt(Stream * s,const DataExtractor & data,lldb::offset_t offset,lldb::offset_t byte_size,bool is_signed,unsigned radix)9874a628f7SDimitry Andric static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
9974a628f7SDimitry Andric lldb::offset_t offset, lldb::offset_t byte_size,
10074a628f7SDimitry Andric bool is_signed, unsigned radix) {
101e3b55780SDimitry Andric std::optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size);
102145449b1SDimitry Andric if (apint) {
103e3b55780SDimitry Andric std::string apint_str = toString(*apint, radix, is_signed);
10474a628f7SDimitry Andric switch (radix) {
10574a628f7SDimitry Andric case 2:
10674a628f7SDimitry Andric s->Write("0b", 2);
10774a628f7SDimitry Andric break;
10874a628f7SDimitry Andric case 8:
10974a628f7SDimitry Andric s->Write("0", 1);
11074a628f7SDimitry Andric break;
11174a628f7SDimitry Andric case 10:
11274a628f7SDimitry Andric break;
11374a628f7SDimitry Andric }
11474a628f7SDimitry Andric s->Write(apint_str.c_str(), apint_str.size());
11574a628f7SDimitry Andric }
11674a628f7SDimitry Andric return offset;
11774a628f7SDimitry Andric }
11874a628f7SDimitry Andric
119cfca06d7SDimitry Andric /// Dumps decoded instructions to a stream.
DumpInstructions(const DataExtractor & DE,Stream * s,ExecutionContextScope * exe_scope,offset_t start_offset,uint64_t base_addr,size_t number_of_instructions)120cfca06d7SDimitry Andric static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,
121cfca06d7SDimitry Andric ExecutionContextScope *exe_scope,
122cfca06d7SDimitry Andric offset_t start_offset,
123cfca06d7SDimitry Andric uint64_t base_addr,
124cfca06d7SDimitry Andric size_t number_of_instructions) {
125cfca06d7SDimitry Andric offset_t offset = start_offset;
126cfca06d7SDimitry Andric
127cfca06d7SDimitry Andric TargetSP target_sp;
128cfca06d7SDimitry Andric if (exe_scope)
129cfca06d7SDimitry Andric target_sp = exe_scope->CalculateTarget();
130cfca06d7SDimitry Andric if (target_sp) {
131cfca06d7SDimitry Andric DisassemblerSP disassembler_sp(
132cfca06d7SDimitry Andric Disassembler::FindPlugin(target_sp->GetArchitecture(),
133cfca06d7SDimitry Andric target_sp->GetDisassemblyFlavor(), nullptr));
134cfca06d7SDimitry Andric if (disassembler_sp) {
135cfca06d7SDimitry Andric lldb::addr_t addr = base_addr + start_offset;
136cfca06d7SDimitry Andric lldb_private::Address so_addr;
137cfca06d7SDimitry Andric bool data_from_file = true;
138cfca06d7SDimitry Andric if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
139cfca06d7SDimitry Andric data_from_file = false;
140cfca06d7SDimitry Andric } else {
141cfca06d7SDimitry Andric if (target_sp->GetSectionLoadList().IsEmpty() ||
142cfca06d7SDimitry Andric !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
143cfca06d7SDimitry Andric so_addr.SetRawAddress(addr);
144cfca06d7SDimitry Andric }
145cfca06d7SDimitry Andric
146cfca06d7SDimitry Andric size_t bytes_consumed = disassembler_sp->DecodeInstructions(
147cfca06d7SDimitry Andric so_addr, DE, start_offset, number_of_instructions, false,
148cfca06d7SDimitry Andric data_from_file);
149cfca06d7SDimitry Andric
150cfca06d7SDimitry Andric if (bytes_consumed) {
151cfca06d7SDimitry Andric offset += bytes_consumed;
152cfca06d7SDimitry Andric const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
153ac9a064cSDimitry Andric const bool show_bytes = false;
154ac9a064cSDimitry Andric const bool show_control_flow_kind = false;
155cfca06d7SDimitry Andric ExecutionContext exe_ctx;
156cfca06d7SDimitry Andric exe_scope->CalculateExecutionContext(exe_ctx);
1571f917f69SDimitry Andric disassembler_sp->GetInstructionList().Dump(
1581f917f69SDimitry Andric s, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
159cfca06d7SDimitry Andric }
160cfca06d7SDimitry Andric }
161cfca06d7SDimitry Andric } else
162cfca06d7SDimitry Andric s->Printf("invalid target");
163cfca06d7SDimitry Andric
164cfca06d7SDimitry Andric return offset;
165cfca06d7SDimitry Andric }
166cfca06d7SDimitry Andric
167cfca06d7SDimitry Andric /// Prints the specific escape sequence of the given character to the stream.
168cfca06d7SDimitry Andric /// If the character doesn't have a known specific escape sequence (e.g., '\a',
169cfca06d7SDimitry Andric /// '\n' but not generic escape sequences such as'\x12'), this function will
170cfca06d7SDimitry Andric /// not modify the stream and return false.
TryDumpSpecialEscapedChar(Stream & s,const char c)171cfca06d7SDimitry Andric static bool TryDumpSpecialEscapedChar(Stream &s, const char c) {
172cfca06d7SDimitry Andric switch (c) {
173cfca06d7SDimitry Andric case '\033':
174cfca06d7SDimitry Andric // Common non-standard escape code for 'escape'.
175cfca06d7SDimitry Andric s.Printf("\\e");
176cfca06d7SDimitry Andric return true;
177cfca06d7SDimitry Andric case '\a':
178cfca06d7SDimitry Andric s.Printf("\\a");
179cfca06d7SDimitry Andric return true;
180cfca06d7SDimitry Andric case '\b':
181cfca06d7SDimitry Andric s.Printf("\\b");
182cfca06d7SDimitry Andric return true;
183cfca06d7SDimitry Andric case '\f':
184cfca06d7SDimitry Andric s.Printf("\\f");
185cfca06d7SDimitry Andric return true;
186cfca06d7SDimitry Andric case '\n':
187cfca06d7SDimitry Andric s.Printf("\\n");
188cfca06d7SDimitry Andric return true;
189cfca06d7SDimitry Andric case '\r':
190cfca06d7SDimitry Andric s.Printf("\\r");
191cfca06d7SDimitry Andric return true;
192cfca06d7SDimitry Andric case '\t':
193cfca06d7SDimitry Andric s.Printf("\\t");
194cfca06d7SDimitry Andric return true;
195cfca06d7SDimitry Andric case '\v':
196cfca06d7SDimitry Andric s.Printf("\\v");
197cfca06d7SDimitry Andric return true;
198cfca06d7SDimitry Andric case '\0':
199cfca06d7SDimitry Andric s.Printf("\\0");
200cfca06d7SDimitry Andric return true;
201cfca06d7SDimitry Andric default:
202cfca06d7SDimitry Andric return false;
203cfca06d7SDimitry Andric }
204cfca06d7SDimitry Andric }
205cfca06d7SDimitry Andric
206cfca06d7SDimitry Andric /// Dump the character to a stream. A character that is not printable will be
207cfca06d7SDimitry Andric /// represented by its escape sequence.
DumpCharacter(Stream & s,const char c)208cfca06d7SDimitry Andric static void DumpCharacter(Stream &s, const char c) {
209cfca06d7SDimitry Andric if (TryDumpSpecialEscapedChar(s, c))
210cfca06d7SDimitry Andric return;
211cfca06d7SDimitry Andric if (llvm::isPrint(c)) {
212cfca06d7SDimitry Andric s.PutChar(c);
213cfca06d7SDimitry Andric return;
214cfca06d7SDimitry Andric }
2157fa27ce4SDimitry Andric s.Printf("\\x%2.2hhx", c);
216cfca06d7SDimitry Andric }
217cfca06d7SDimitry Andric
218344a3780SDimitry Andric /// Dump a floating point type.
219344a3780SDimitry Andric template <typename FloatT>
DumpFloatingPoint(std::ostringstream & ss,FloatT f)220344a3780SDimitry Andric void DumpFloatingPoint(std::ostringstream &ss, FloatT f) {
221344a3780SDimitry Andric static_assert(std::is_floating_point<FloatT>::value,
222344a3780SDimitry Andric "Only floating point types can be dumped.");
223344a3780SDimitry Andric // NaN and Inf are potentially implementation defined and on Darwin it
224344a3780SDimitry Andric // seems NaNs are printed without their sign. Manually implement dumping them
225344a3780SDimitry Andric // here to avoid having to deal with platform differences.
226344a3780SDimitry Andric if (std::isnan(f)) {
227344a3780SDimitry Andric if (std::signbit(f))
228344a3780SDimitry Andric ss << '-';
229344a3780SDimitry Andric ss << "nan";
230344a3780SDimitry Andric return;
231344a3780SDimitry Andric }
232344a3780SDimitry Andric if (std::isinf(f)) {
233344a3780SDimitry Andric if (std::signbit(f))
234344a3780SDimitry Andric ss << '-';
235344a3780SDimitry Andric ss << "inf";
236344a3780SDimitry Andric return;
237344a3780SDimitry Andric }
238344a3780SDimitry Andric ss << f;
239344a3780SDimitry Andric }
240344a3780SDimitry Andric
241e3b55780SDimitry Andric static std::optional<MemoryTagMap>
GetMemoryTags(lldb::addr_t addr,size_t length,ExecutionContextScope * exe_scope)2426f8fc217SDimitry Andric GetMemoryTags(lldb::addr_t addr, size_t length,
2436f8fc217SDimitry Andric ExecutionContextScope *exe_scope) {
2446f8fc217SDimitry Andric assert(addr != LLDB_INVALID_ADDRESS);
2456f8fc217SDimitry Andric
2466f8fc217SDimitry Andric if (!exe_scope)
247e3b55780SDimitry Andric return std::nullopt;
2486f8fc217SDimitry Andric
2496f8fc217SDimitry Andric TargetSP target_sp = exe_scope->CalculateTarget();
2506f8fc217SDimitry Andric if (!target_sp)
251e3b55780SDimitry Andric return std::nullopt;
2526f8fc217SDimitry Andric
2536f8fc217SDimitry Andric ProcessSP process_sp = target_sp->CalculateProcess();
2546f8fc217SDimitry Andric if (!process_sp)
255e3b55780SDimitry Andric return std::nullopt;
2566f8fc217SDimitry Andric
2576f8fc217SDimitry Andric llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
2586f8fc217SDimitry Andric process_sp->GetMemoryTagManager();
2596f8fc217SDimitry Andric if (!tag_manager_or_err) {
2606f8fc217SDimitry Andric llvm::consumeError(tag_manager_or_err.takeError());
261e3b55780SDimitry Andric return std::nullopt;
2626f8fc217SDimitry Andric }
2636f8fc217SDimitry Andric
2646f8fc217SDimitry Andric MemoryRegionInfos memory_regions;
2656f8fc217SDimitry Andric // Don't check return status, list will be just empty if an error happened.
2666f8fc217SDimitry Andric process_sp->GetMemoryRegions(memory_regions);
2676f8fc217SDimitry Andric
2686f8fc217SDimitry Andric llvm::Expected<std::vector<MemoryTagManager::TagRange>> tagged_ranges_or_err =
2696f8fc217SDimitry Andric (*tag_manager_or_err)
2706f8fc217SDimitry Andric ->MakeTaggedRanges(addr, addr + length, memory_regions);
2716f8fc217SDimitry Andric // Here we know that our range will not be inverted but we must still check
2726f8fc217SDimitry Andric // for an error.
2736f8fc217SDimitry Andric if (!tagged_ranges_or_err) {
2746f8fc217SDimitry Andric llvm::consumeError(tagged_ranges_or_err.takeError());
275e3b55780SDimitry Andric return std::nullopt;
2766f8fc217SDimitry Andric }
2776f8fc217SDimitry Andric if (tagged_ranges_or_err->empty())
278e3b55780SDimitry Andric return std::nullopt;
2796f8fc217SDimitry Andric
2806f8fc217SDimitry Andric MemoryTagMap memory_tag_map(*tag_manager_or_err);
2816f8fc217SDimitry Andric for (const MemoryTagManager::TagRange &range : *tagged_ranges_or_err) {
2826f8fc217SDimitry Andric llvm::Expected<std::vector<lldb::addr_t>> tags_or_err =
2836f8fc217SDimitry Andric process_sp->ReadMemoryTags(range.GetRangeBase(), range.GetByteSize());
2846f8fc217SDimitry Andric
2856f8fc217SDimitry Andric if (tags_or_err)
2866f8fc217SDimitry Andric memory_tag_map.InsertTags(range.GetRangeBase(), *tags_or_err);
2876f8fc217SDimitry Andric else
2886f8fc217SDimitry Andric llvm::consumeError(tags_or_err.takeError());
2896f8fc217SDimitry Andric }
2906f8fc217SDimitry Andric
2916f8fc217SDimitry Andric if (memory_tag_map.Empty())
292e3b55780SDimitry Andric return std::nullopt;
2936f8fc217SDimitry Andric
2946f8fc217SDimitry Andric return memory_tag_map;
2956f8fc217SDimitry Andric }
2966f8fc217SDimitry Andric
printMemoryTags(const DataExtractor & DE,Stream * s,lldb::addr_t addr,size_t len,const std::optional<MemoryTagMap> & memory_tag_map)297e3b55780SDimitry Andric static void printMemoryTags(const DataExtractor &DE, Stream *s,
298e3b55780SDimitry Andric lldb::addr_t addr, size_t len,
299e3b55780SDimitry Andric const std::optional<MemoryTagMap> &memory_tag_map) {
300e3b55780SDimitry Andric std::vector<std::optional<lldb::addr_t>> tags =
3016f8fc217SDimitry Andric memory_tag_map->GetTags(addr, len);
3026f8fc217SDimitry Andric
3036f8fc217SDimitry Andric // Only print if there is at least one tag for this line
3046f8fc217SDimitry Andric if (tags.empty())
3056f8fc217SDimitry Andric return;
3066f8fc217SDimitry Andric
3076f8fc217SDimitry Andric s->Printf(" (tag%s:", tags.size() > 1 ? "s" : "");
3086f8fc217SDimitry Andric // Some granules may not be tagged but print something for them
3096f8fc217SDimitry Andric // so that the ordering remains intact.
3106f8fc217SDimitry Andric for (auto tag : tags) {
3116f8fc217SDimitry Andric if (tag)
3126f8fc217SDimitry Andric s->Printf(" 0x%" PRIx64, *tag);
3136f8fc217SDimitry Andric else
3146f8fc217SDimitry Andric s->PutCString(" <no tag>");
3156f8fc217SDimitry Andric }
3166f8fc217SDimitry Andric s->PutCString(")");
3176f8fc217SDimitry Andric }
3186f8fc217SDimitry Andric
GetFloatSemantics(const TargetSP & target_sp,size_t byte_size)319e3b55780SDimitry Andric static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
320e3b55780SDimitry Andric size_t byte_size) {
321e3b55780SDimitry Andric if (target_sp) {
322e3b55780SDimitry Andric auto type_system_or_err =
323e3b55780SDimitry Andric target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
324e3b55780SDimitry Andric if (!type_system_or_err)
325e3b55780SDimitry Andric llvm::consumeError(type_system_or_err.takeError());
326e3b55780SDimitry Andric else if (auto ts = *type_system_or_err)
327e3b55780SDimitry Andric return ts->GetFloatTypeSemantics(byte_size);
328e3b55780SDimitry Andric }
329e3b55780SDimitry Andric // No target, just make a reasonable guess
330e3b55780SDimitry Andric switch(byte_size) {
331e3b55780SDimitry Andric case 2:
332e3b55780SDimitry Andric return llvm::APFloat::IEEEhalf();
333e3b55780SDimitry Andric case 4:
334e3b55780SDimitry Andric return llvm::APFloat::IEEEsingle();
335e3b55780SDimitry Andric case 8:
336e3b55780SDimitry Andric return llvm::APFloat::IEEEdouble();
337e3b55780SDimitry Andric }
338e3b55780SDimitry Andric return llvm::APFloat::Bogus();
339e3b55780SDimitry Andric }
340e3b55780SDimitry Andric
DumpDataExtractor(const DataExtractor & DE,Stream * s,offset_t start_offset,lldb::Format item_format,size_t item_byte_size,size_t item_count,size_t num_per_line,uint64_t base_addr,uint32_t item_bit_size,uint32_t item_bit_offset,ExecutionContextScope * exe_scope,bool show_memory_tags)34174a628f7SDimitry Andric lldb::offset_t lldb_private::DumpDataExtractor(
34274a628f7SDimitry Andric const DataExtractor &DE, Stream *s, offset_t start_offset,
34374a628f7SDimitry Andric lldb::Format item_format, size_t item_byte_size, size_t item_count,
34474a628f7SDimitry Andric size_t num_per_line, uint64_t base_addr,
34574a628f7SDimitry Andric uint32_t item_bit_size, // If zero, this is not a bitfield value, if
34674a628f7SDimitry Andric // non-zero, the value is a bitfield
34774a628f7SDimitry Andric uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
34874a628f7SDimitry Andric // shift amount to apply to a bitfield
3496f8fc217SDimitry Andric ExecutionContextScope *exe_scope, bool show_memory_tags) {
35074a628f7SDimitry Andric if (s == nullptr)
35174a628f7SDimitry Andric return start_offset;
35274a628f7SDimitry Andric
35374a628f7SDimitry Andric if (item_format == eFormatPointer) {
35474a628f7SDimitry Andric if (item_byte_size != 4 && item_byte_size != 8)
35574a628f7SDimitry Andric item_byte_size = s->GetAddressByteSize();
35674a628f7SDimitry Andric }
35774a628f7SDimitry Andric
35874a628f7SDimitry Andric offset_t offset = start_offset;
35974a628f7SDimitry Andric
360e3b55780SDimitry Andric std::optional<MemoryTagMap> memory_tag_map;
3616f8fc217SDimitry Andric if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS)
3626f8fc217SDimitry Andric memory_tag_map =
3636f8fc217SDimitry Andric GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope);
3646f8fc217SDimitry Andric
365cfca06d7SDimitry Andric if (item_format == eFormatInstruction)
366cfca06d7SDimitry Andric return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
367cfca06d7SDimitry Andric item_count);
36874a628f7SDimitry Andric
36974a628f7SDimitry Andric if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
37074a628f7SDimitry Andric item_byte_size > 8)
37174a628f7SDimitry Andric item_format = eFormatHex;
37274a628f7SDimitry Andric
37374a628f7SDimitry Andric lldb::offset_t line_start_offset = start_offset;
37474a628f7SDimitry Andric for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
37574a628f7SDimitry Andric ++count) {
3766f8fc217SDimitry Andric // If we are at the beginning or end of a line
3776f8fc217SDimitry Andric // Note that the last line is handled outside this for loop.
37874a628f7SDimitry Andric if ((count % num_per_line) == 0) {
3796f8fc217SDimitry Andric // If we are at the end of a line
38074a628f7SDimitry Andric if (count > 0) {
38174a628f7SDimitry Andric if (item_format == eFormatBytesWithASCII &&
38274a628f7SDimitry Andric offset > line_start_offset) {
38374a628f7SDimitry Andric s->Printf("%*s",
38474a628f7SDimitry Andric static_cast<int>(
38574a628f7SDimitry Andric (num_per_line - (offset - line_start_offset)) * 3 + 2),
38674a628f7SDimitry Andric "");
38774a628f7SDimitry Andric DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
38874a628f7SDimitry Andric offset - line_start_offset, SIZE_MAX,
38974a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
39074a628f7SDimitry Andric }
3916f8fc217SDimitry Andric
3926f8fc217SDimitry Andric if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
3936f8fc217SDimitry Andric size_t line_len = offset - line_start_offset;
3946f8fc217SDimitry Andric lldb::addr_t line_base =
3956f8fc217SDimitry Andric base_addr +
3966f8fc217SDimitry Andric (offset - start_offset - line_len) / DE.getTargetByteSize();
3976f8fc217SDimitry Andric printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
3986f8fc217SDimitry Andric }
3996f8fc217SDimitry Andric
40074a628f7SDimitry Andric s->EOL();
40174a628f7SDimitry Andric }
40274a628f7SDimitry Andric if (base_addr != LLDB_INVALID_ADDRESS)
40374a628f7SDimitry Andric s->Printf("0x%8.8" PRIx64 ": ",
40474a628f7SDimitry Andric (uint64_t)(base_addr +
40574a628f7SDimitry Andric (offset - start_offset) / DE.getTargetByteSize()));
40674a628f7SDimitry Andric
40774a628f7SDimitry Andric line_start_offset = offset;
40874a628f7SDimitry Andric } else if (item_format != eFormatChar &&
40974a628f7SDimitry Andric item_format != eFormatCharPrintable &&
41074a628f7SDimitry Andric item_format != eFormatCharArray && count > 0) {
41174a628f7SDimitry Andric s->PutChar(' ');
41274a628f7SDimitry Andric }
41374a628f7SDimitry Andric
41474a628f7SDimitry Andric switch (item_format) {
41574a628f7SDimitry Andric case eFormatBoolean:
41674a628f7SDimitry Andric if (item_byte_size <= 8)
41774a628f7SDimitry Andric s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
41874a628f7SDimitry Andric item_bit_size, item_bit_offset)
41974a628f7SDimitry Andric ? "true"
42074a628f7SDimitry Andric : "false");
42174a628f7SDimitry Andric else {
42274a628f7SDimitry Andric s->Printf("error: unsupported byte size (%" PRIu64
42374a628f7SDimitry Andric ") for boolean format",
42474a628f7SDimitry Andric (uint64_t)item_byte_size);
42574a628f7SDimitry Andric return offset;
42674a628f7SDimitry Andric }
42774a628f7SDimitry Andric break;
42874a628f7SDimitry Andric
42974a628f7SDimitry Andric case eFormatBinary:
43074a628f7SDimitry Andric if (item_byte_size <= 8) {
43174a628f7SDimitry Andric uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
43274a628f7SDimitry Andric item_bit_size, item_bit_offset);
433f73363f1SDimitry Andric // Avoid std::bitset<64>::to_string() since it is missing in earlier
434f73363f1SDimitry Andric // C++ libraries
43574a628f7SDimitry Andric std::string binary_value(64, '0');
43674a628f7SDimitry Andric std::bitset<64> bits(uval64);
43774a628f7SDimitry Andric for (uint32_t i = 0; i < 64; ++i)
43874a628f7SDimitry Andric if (bits[i])
43974a628f7SDimitry Andric binary_value[64 - 1 - i] = '1';
44074a628f7SDimitry Andric if (item_bit_size > 0)
44174a628f7SDimitry Andric s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
44274a628f7SDimitry Andric else if (item_byte_size > 0 && item_byte_size <= 8)
44374a628f7SDimitry Andric s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
44474a628f7SDimitry Andric } else {
44574a628f7SDimitry Andric const bool is_signed = false;
44674a628f7SDimitry Andric const unsigned radix = 2;
44774a628f7SDimitry Andric offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
44874a628f7SDimitry Andric }
44974a628f7SDimitry Andric break;
45074a628f7SDimitry Andric
45174a628f7SDimitry Andric case eFormatBytes:
45274a628f7SDimitry Andric case eFormatBytesWithASCII:
45374a628f7SDimitry Andric for (uint32_t i = 0; i < item_byte_size; ++i) {
45474a628f7SDimitry Andric s->Printf("%2.2x", DE.GetU8(&offset));
45574a628f7SDimitry Andric }
45674a628f7SDimitry Andric
457f73363f1SDimitry Andric // Put an extra space between the groups of bytes if more than one is
458f73363f1SDimitry Andric // being dumped in a group (item_byte_size is more than 1).
45974a628f7SDimitry Andric if (item_byte_size > 1)
46074a628f7SDimitry Andric s->PutChar(' ');
46174a628f7SDimitry Andric break;
46274a628f7SDimitry Andric
46374a628f7SDimitry Andric case eFormatChar:
46474a628f7SDimitry Andric case eFormatCharPrintable:
46574a628f7SDimitry Andric case eFormatCharArray: {
466ef5d0b5eSDimitry Andric // Reject invalid item_byte_size.
467ef5d0b5eSDimitry Andric if (item_byte_size > 8) {
468ef5d0b5eSDimitry Andric s->Printf("error: unsupported byte size (%" PRIu64 ") for char format",
469ef5d0b5eSDimitry Andric (uint64_t)item_byte_size);
470ef5d0b5eSDimitry Andric return offset;
471ef5d0b5eSDimitry Andric }
472ef5d0b5eSDimitry Andric
473f73363f1SDimitry Andric // If we are only printing one character surround it with single quotes
47474a628f7SDimitry Andric if (item_count == 1 && item_format == eFormatChar)
47574a628f7SDimitry Andric s->PutChar('\'');
47674a628f7SDimitry Andric
47774a628f7SDimitry Andric const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,
47874a628f7SDimitry Andric item_bit_size, item_bit_offset);
479cfca06d7SDimitry Andric if (llvm::isPrint(ch))
48074a628f7SDimitry Andric s->Printf("%c", (char)ch);
48174a628f7SDimitry Andric else if (item_format != eFormatCharPrintable) {
482cfca06d7SDimitry Andric if (!TryDumpSpecialEscapedChar(*s, ch)) {
48374a628f7SDimitry Andric if (item_byte_size == 1)
48474a628f7SDimitry Andric s->Printf("\\x%2.2x", (uint8_t)ch);
48574a628f7SDimitry Andric else
48674a628f7SDimitry Andric s->Printf("%" PRIu64, ch);
48774a628f7SDimitry Andric }
48874a628f7SDimitry Andric } else {
48974a628f7SDimitry Andric s->PutChar(NON_PRINTABLE_CHAR);
49074a628f7SDimitry Andric }
49174a628f7SDimitry Andric
49274a628f7SDimitry Andric // If we are only printing one character surround it with single quotes
49374a628f7SDimitry Andric if (item_count == 1 && item_format == eFormatChar)
49474a628f7SDimitry Andric s->PutChar('\'');
49574a628f7SDimitry Andric } break;
49674a628f7SDimitry Andric
49774a628f7SDimitry Andric case eFormatEnum: // Print enum value as a signed integer when we don't get
49874a628f7SDimitry Andric // the enum type
49974a628f7SDimitry Andric case eFormatDecimal:
50074a628f7SDimitry Andric if (item_byte_size <= 8)
50174a628f7SDimitry Andric s->Printf("%" PRId64,
50274a628f7SDimitry Andric DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
50374a628f7SDimitry Andric item_bit_offset));
50474a628f7SDimitry Andric else {
50574a628f7SDimitry Andric const bool is_signed = true;
50674a628f7SDimitry Andric const unsigned radix = 10;
50774a628f7SDimitry Andric offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
50874a628f7SDimitry Andric }
50974a628f7SDimitry Andric break;
51074a628f7SDimitry Andric
51174a628f7SDimitry Andric case eFormatUnsigned:
51274a628f7SDimitry Andric if (item_byte_size <= 8)
51374a628f7SDimitry Andric s->Printf("%" PRIu64,
51474a628f7SDimitry Andric DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
51574a628f7SDimitry Andric item_bit_offset));
51674a628f7SDimitry Andric else {
51774a628f7SDimitry Andric const bool is_signed = false;
51874a628f7SDimitry Andric const unsigned radix = 10;
51974a628f7SDimitry Andric offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
52074a628f7SDimitry Andric }
52174a628f7SDimitry Andric break;
52274a628f7SDimitry Andric
52374a628f7SDimitry Andric case eFormatOctal:
52474a628f7SDimitry Andric if (item_byte_size <= 8)
52574a628f7SDimitry Andric s->Printf("0%" PRIo64,
52674a628f7SDimitry Andric DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
52774a628f7SDimitry Andric item_bit_offset));
52874a628f7SDimitry Andric else {
52974a628f7SDimitry Andric const bool is_signed = false;
53074a628f7SDimitry Andric const unsigned radix = 8;
53174a628f7SDimitry Andric offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
53274a628f7SDimitry Andric }
53374a628f7SDimitry Andric break;
53474a628f7SDimitry Andric
53574a628f7SDimitry Andric case eFormatOSType: {
53674a628f7SDimitry Andric uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
53774a628f7SDimitry Andric item_bit_size, item_bit_offset);
53874a628f7SDimitry Andric s->PutChar('\'');
53974a628f7SDimitry Andric for (uint32_t i = 0; i < item_byte_size; ++i) {
54074a628f7SDimitry Andric uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
541cfca06d7SDimitry Andric DumpCharacter(*s, ch);
54274a628f7SDimitry Andric }
54374a628f7SDimitry Andric s->PutChar('\'');
54474a628f7SDimitry Andric } break;
54574a628f7SDimitry Andric
54674a628f7SDimitry Andric case eFormatCString: {
54774a628f7SDimitry Andric const char *cstr = DE.GetCStr(&offset);
54874a628f7SDimitry Andric
54974a628f7SDimitry Andric if (!cstr) {
55074a628f7SDimitry Andric s->Printf("NULL");
55174a628f7SDimitry Andric offset = LLDB_INVALID_OFFSET;
55274a628f7SDimitry Andric } else {
55374a628f7SDimitry Andric s->PutChar('\"');
55474a628f7SDimitry Andric
55574a628f7SDimitry Andric while (const char c = *cstr) {
556cfca06d7SDimitry Andric DumpCharacter(*s, c);
55774a628f7SDimitry Andric ++cstr;
55874a628f7SDimitry Andric }
55974a628f7SDimitry Andric
56074a628f7SDimitry Andric s->PutChar('\"');
56174a628f7SDimitry Andric }
56274a628f7SDimitry Andric } break;
56374a628f7SDimitry Andric
56474a628f7SDimitry Andric case eFormatPointer:
565706b4fc4SDimitry Andric DumpAddress(s->AsRawOstream(),
566706b4fc4SDimitry Andric DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
56774a628f7SDimitry Andric item_bit_offset),
56874a628f7SDimitry Andric sizeof(addr_t));
56974a628f7SDimitry Andric break;
57074a628f7SDimitry Andric
57174a628f7SDimitry Andric case eFormatComplexInteger: {
57274a628f7SDimitry Andric size_t complex_int_byte_size = item_byte_size / 2;
57374a628f7SDimitry Andric
57474a628f7SDimitry Andric if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
57574a628f7SDimitry Andric s->Printf("%" PRIu64,
57674a628f7SDimitry Andric DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
57774a628f7SDimitry Andric s->Printf(" + %" PRIu64 "i",
57874a628f7SDimitry Andric DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
57974a628f7SDimitry Andric } else {
58074a628f7SDimitry Andric s->Printf("error: unsupported byte size (%" PRIu64
58174a628f7SDimitry Andric ") for complex integer format",
58274a628f7SDimitry Andric (uint64_t)item_byte_size);
58374a628f7SDimitry Andric return offset;
58474a628f7SDimitry Andric }
58574a628f7SDimitry Andric } break;
58674a628f7SDimitry Andric
58774a628f7SDimitry Andric case eFormatComplex:
58874a628f7SDimitry Andric if (sizeof(float) * 2 == item_byte_size) {
58974a628f7SDimitry Andric float f32_1 = DE.GetFloat(&offset);
59074a628f7SDimitry Andric float f32_2 = DE.GetFloat(&offset);
59174a628f7SDimitry Andric
59274a628f7SDimitry Andric s->Printf("%g + %gi", f32_1, f32_2);
59374a628f7SDimitry Andric break;
59474a628f7SDimitry Andric } else if (sizeof(double) * 2 == item_byte_size) {
59574a628f7SDimitry Andric double d64_1 = DE.GetDouble(&offset);
59674a628f7SDimitry Andric double d64_2 = DE.GetDouble(&offset);
59774a628f7SDimitry Andric
59874a628f7SDimitry Andric s->Printf("%lg + %lgi", d64_1, d64_2);
59974a628f7SDimitry Andric break;
60074a628f7SDimitry Andric } else if (sizeof(long double) * 2 == item_byte_size) {
60174a628f7SDimitry Andric long double ld64_1 = DE.GetLongDouble(&offset);
60274a628f7SDimitry Andric long double ld64_2 = DE.GetLongDouble(&offset);
60374a628f7SDimitry Andric s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
60474a628f7SDimitry Andric break;
60574a628f7SDimitry Andric } else {
60674a628f7SDimitry Andric s->Printf("error: unsupported byte size (%" PRIu64
60774a628f7SDimitry Andric ") for complex float format",
60874a628f7SDimitry Andric (uint64_t)item_byte_size);
60974a628f7SDimitry Andric return offset;
61074a628f7SDimitry Andric }
61174a628f7SDimitry Andric break;
61274a628f7SDimitry Andric
61374a628f7SDimitry Andric default:
61474a628f7SDimitry Andric case eFormatDefault:
61574a628f7SDimitry Andric case eFormatHex:
61674a628f7SDimitry Andric case eFormatHexUppercase: {
61774a628f7SDimitry Andric bool wantsuppercase = (item_format == eFormatHexUppercase);
61874a628f7SDimitry Andric switch (item_byte_size) {
61974a628f7SDimitry Andric case 1:
62074a628f7SDimitry Andric case 2:
62174a628f7SDimitry Andric case 4:
62274a628f7SDimitry Andric case 8:
623b1c73532SDimitry Andric if (Target::GetGlobalProperties()
624b1c73532SDimitry Andric .ShowHexVariableValuesWithLeadingZeroes()) {
62574a628f7SDimitry Andric s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
62674a628f7SDimitry Andric (int)(2 * item_byte_size), (int)(2 * item_byte_size),
62774a628f7SDimitry Andric DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
62874a628f7SDimitry Andric item_bit_offset));
629b1c73532SDimitry Andric } else {
630b1c73532SDimitry Andric s->Printf(wantsuppercase ? "0x%" PRIX64 : "0x%" PRIx64,
631b1c73532SDimitry Andric DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
632b1c73532SDimitry Andric item_bit_offset));
633b1c73532SDimitry Andric }
63474a628f7SDimitry Andric break;
63574a628f7SDimitry Andric default: {
63674a628f7SDimitry Andric assert(item_bit_size == 0 && item_bit_offset == 0);
63774a628f7SDimitry Andric const uint8_t *bytes =
63874a628f7SDimitry Andric (const uint8_t *)DE.GetData(&offset, item_byte_size);
63974a628f7SDimitry Andric if (bytes) {
64074a628f7SDimitry Andric s->PutCString("0x");
64174a628f7SDimitry Andric uint32_t idx;
64274a628f7SDimitry Andric if (DE.GetByteOrder() == eByteOrderBig) {
64374a628f7SDimitry Andric for (idx = 0; idx < item_byte_size; ++idx)
64474a628f7SDimitry Andric s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
64574a628f7SDimitry Andric } else {
64674a628f7SDimitry Andric for (idx = 0; idx < item_byte_size; ++idx)
64774a628f7SDimitry Andric s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
64874a628f7SDimitry Andric bytes[item_byte_size - 1 - idx]);
64974a628f7SDimitry Andric }
65074a628f7SDimitry Andric }
65174a628f7SDimitry Andric } break;
65274a628f7SDimitry Andric }
65374a628f7SDimitry Andric } break;
65474a628f7SDimitry Andric
65574a628f7SDimitry Andric case eFormatFloat: {
65674a628f7SDimitry Andric TargetSP target_sp;
65774a628f7SDimitry Andric if (exe_scope)
65874a628f7SDimitry Andric target_sp = exe_scope->CalculateTarget();
659e3b55780SDimitry Andric
660e3b55780SDimitry Andric std::optional<unsigned> format_max_padding;
661e3b55780SDimitry Andric if (target_sp)
662e3b55780SDimitry Andric format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat();
663e3b55780SDimitry Andric
66474a628f7SDimitry Andric // Show full precision when printing float values
66574a628f7SDimitry Andric const unsigned format_precision = 0;
66674a628f7SDimitry Andric
667e3b55780SDimitry Andric const llvm::fltSemantics &semantics =
668e3b55780SDimitry Andric GetFloatSemantics(target_sp, item_byte_size);
669f73363f1SDimitry Andric
670ead24645SDimitry Andric // Recalculate the byte size in case of a difference. This is possible
671ead24645SDimitry Andric // when item_byte_size is 16 (128-bit), because you could get back the
672ead24645SDimitry Andric // x87DoubleExtended semantics which has a byte size of 10 (80-bit).
673ead24645SDimitry Andric const size_t semantics_byte_size =
674ead24645SDimitry Andric (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
675e3b55780SDimitry Andric std::optional<llvm::APInt> apint =
676ead24645SDimitry Andric GetAPInt(DE, &offset, semantics_byte_size);
677145449b1SDimitry Andric if (apint) {
678e3b55780SDimitry Andric llvm::APFloat apfloat(semantics, *apint);
679e3b55780SDimitry Andric llvm::SmallVector<char, 256> sv;
680e3b55780SDimitry Andric if (format_max_padding)
681e3b55780SDimitry Andric apfloat.toString(sv, format_precision, *format_max_padding);
682e3b55780SDimitry Andric else
683e3b55780SDimitry Andric apfloat.toString(sv, format_precision);
684e3b55780SDimitry Andric s->AsRawOstream() << sv;
68574a628f7SDimitry Andric } else {
686e3b55780SDimitry Andric s->Format("error: unsupported byte size ({0}) for float format",
687e3b55780SDimitry Andric item_byte_size);
68874a628f7SDimitry Andric return offset;
68974a628f7SDimitry Andric }
69074a628f7SDimitry Andric } break;
69174a628f7SDimitry Andric
69274a628f7SDimitry Andric case eFormatUnicode16:
69374a628f7SDimitry Andric s->Printf("U+%4.4x", DE.GetU16(&offset));
69474a628f7SDimitry Andric break;
69574a628f7SDimitry Andric
69674a628f7SDimitry Andric case eFormatUnicode32:
69774a628f7SDimitry Andric s->Printf("U+0x%8.8x", DE.GetU32(&offset));
69874a628f7SDimitry Andric break;
69974a628f7SDimitry Andric
70074a628f7SDimitry Andric case eFormatAddressInfo: {
70174a628f7SDimitry Andric addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
70274a628f7SDimitry Andric item_bit_offset);
70374a628f7SDimitry Andric s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
70474a628f7SDimitry Andric (int)(2 * item_byte_size), addr);
70574a628f7SDimitry Andric if (exe_scope) {
70674a628f7SDimitry Andric TargetSP target_sp(exe_scope->CalculateTarget());
70774a628f7SDimitry Andric lldb_private::Address so_addr;
70874a628f7SDimitry Andric if (target_sp) {
70974a628f7SDimitry Andric if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
71074a628f7SDimitry Andric so_addr)) {
71174a628f7SDimitry Andric s->PutChar(' ');
71274a628f7SDimitry Andric so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
71374a628f7SDimitry Andric Address::DumpStyleModuleWithFileAddress);
71474a628f7SDimitry Andric } else {
71574a628f7SDimitry Andric so_addr.SetOffset(addr);
71674a628f7SDimitry Andric so_addr.Dump(s, exe_scope,
71774a628f7SDimitry Andric Address::DumpStyleResolvedPointerDescription);
718344a3780SDimitry Andric if (ProcessSP process_sp = exe_scope->CalculateProcess()) {
719344a3780SDimitry Andric if (ABISP abi_sp = process_sp->GetABI()) {
720344a3780SDimitry Andric addr_t addr_fixed = abi_sp->FixCodeAddress(addr);
721344a3780SDimitry Andric if (target_sp->GetSectionLoadList().ResolveLoadAddress(
722344a3780SDimitry Andric addr_fixed, so_addr)) {
723344a3780SDimitry Andric s->PutChar(' ');
724344a3780SDimitry Andric s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),
725344a3780SDimitry Andric (int)(2 * item_byte_size), addr_fixed);
726344a3780SDimitry Andric s->PutChar(' ');
727344a3780SDimitry Andric so_addr.Dump(s, exe_scope,
728344a3780SDimitry Andric Address::DumpStyleResolvedDescription,
729344a3780SDimitry Andric Address::DumpStyleModuleWithFileAddress);
730344a3780SDimitry Andric }
731344a3780SDimitry Andric }
732344a3780SDimitry Andric }
73374a628f7SDimitry Andric }
73474a628f7SDimitry Andric }
73574a628f7SDimitry Andric }
73674a628f7SDimitry Andric } break;
73774a628f7SDimitry Andric
73874a628f7SDimitry Andric case eFormatHexFloat:
73974a628f7SDimitry Andric if (sizeof(float) == item_byte_size) {
74074a628f7SDimitry Andric char float_cstr[256];
74174a628f7SDimitry Andric llvm::APFloat ap_float(DE.GetFloat(&offset));
74274a628f7SDimitry Andric ap_float.convertToHexString(float_cstr, 0, false,
74374a628f7SDimitry Andric llvm::APFloat::rmNearestTiesToEven);
74474a628f7SDimitry Andric s->Printf("%s", float_cstr);
74574a628f7SDimitry Andric break;
74674a628f7SDimitry Andric } else if (sizeof(double) == item_byte_size) {
74774a628f7SDimitry Andric char float_cstr[256];
74874a628f7SDimitry Andric llvm::APFloat ap_float(DE.GetDouble(&offset));
74974a628f7SDimitry Andric ap_float.convertToHexString(float_cstr, 0, false,
75074a628f7SDimitry Andric llvm::APFloat::rmNearestTiesToEven);
75174a628f7SDimitry Andric s->Printf("%s", float_cstr);
75274a628f7SDimitry Andric break;
75374a628f7SDimitry Andric } else {
75474a628f7SDimitry Andric s->Printf("error: unsupported byte size (%" PRIu64
75574a628f7SDimitry Andric ") for hex float format",
75674a628f7SDimitry Andric (uint64_t)item_byte_size);
75774a628f7SDimitry Andric return offset;
75874a628f7SDimitry Andric }
75974a628f7SDimitry Andric break;
76074a628f7SDimitry Andric
76174a628f7SDimitry Andric // please keep the single-item formats below in sync with
762f73363f1SDimitry Andric // FormatManager::GetSingleItemFormat if you fail to do so, users will
763f73363f1SDimitry Andric // start getting different outputs depending on internal implementation
764f73363f1SDimitry Andric // details they should not care about ||
76574a628f7SDimitry Andric case eFormatVectorOfChar: // ||
76674a628f7SDimitry Andric s->PutChar('{'); // \/
76774a628f7SDimitry Andric offset =
76874a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
76974a628f7SDimitry Andric item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
77074a628f7SDimitry Andric s->PutChar('}');
77174a628f7SDimitry Andric break;
77274a628f7SDimitry Andric
77374a628f7SDimitry Andric case eFormatVectorOfSInt8:
77474a628f7SDimitry Andric s->PutChar('{');
77574a628f7SDimitry Andric offset =
77674a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
77774a628f7SDimitry Andric item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
77874a628f7SDimitry Andric s->PutChar('}');
77974a628f7SDimitry Andric break;
78074a628f7SDimitry Andric
78174a628f7SDimitry Andric case eFormatVectorOfUInt8:
78274a628f7SDimitry Andric s->PutChar('{');
78374a628f7SDimitry Andric offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
78474a628f7SDimitry Andric item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
78574a628f7SDimitry Andric s->PutChar('}');
78674a628f7SDimitry Andric break;
78774a628f7SDimitry Andric
78874a628f7SDimitry Andric case eFormatVectorOfSInt16:
78974a628f7SDimitry Andric s->PutChar('{');
79074a628f7SDimitry Andric offset = DumpDataExtractor(
79174a628f7SDimitry Andric DE, s, offset, eFormatDecimal, sizeof(uint16_t),
79274a628f7SDimitry Andric item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
79374a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
79474a628f7SDimitry Andric s->PutChar('}');
79574a628f7SDimitry Andric break;
79674a628f7SDimitry Andric
79774a628f7SDimitry Andric case eFormatVectorOfUInt16:
79874a628f7SDimitry Andric s->PutChar('{');
79974a628f7SDimitry Andric offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
80074a628f7SDimitry Andric item_byte_size / sizeof(uint16_t),
80174a628f7SDimitry Andric item_byte_size / sizeof(uint16_t),
80274a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
80374a628f7SDimitry Andric s->PutChar('}');
80474a628f7SDimitry Andric break;
80574a628f7SDimitry Andric
80674a628f7SDimitry Andric case eFormatVectorOfSInt32:
80774a628f7SDimitry Andric s->PutChar('{');
80874a628f7SDimitry Andric offset = DumpDataExtractor(
80974a628f7SDimitry Andric DE, s, offset, eFormatDecimal, sizeof(uint32_t),
81074a628f7SDimitry Andric item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
81174a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
81274a628f7SDimitry Andric s->PutChar('}');
81374a628f7SDimitry Andric break;
81474a628f7SDimitry Andric
81574a628f7SDimitry Andric case eFormatVectorOfUInt32:
81674a628f7SDimitry Andric s->PutChar('{');
81774a628f7SDimitry Andric offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
81874a628f7SDimitry Andric item_byte_size / sizeof(uint32_t),
81974a628f7SDimitry Andric item_byte_size / sizeof(uint32_t),
82074a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
82174a628f7SDimitry Andric s->PutChar('}');
82274a628f7SDimitry Andric break;
82374a628f7SDimitry Andric
82474a628f7SDimitry Andric case eFormatVectorOfSInt64:
82574a628f7SDimitry Andric s->PutChar('{');
82674a628f7SDimitry Andric offset = DumpDataExtractor(
82774a628f7SDimitry Andric DE, s, offset, eFormatDecimal, sizeof(uint64_t),
82874a628f7SDimitry Andric item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
82974a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
83074a628f7SDimitry Andric s->PutChar('}');
83174a628f7SDimitry Andric break;
83274a628f7SDimitry Andric
83374a628f7SDimitry Andric case eFormatVectorOfUInt64:
83474a628f7SDimitry Andric s->PutChar('{');
83574a628f7SDimitry Andric offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
83674a628f7SDimitry Andric item_byte_size / sizeof(uint64_t),
83774a628f7SDimitry Andric item_byte_size / sizeof(uint64_t),
83874a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
83974a628f7SDimitry Andric s->PutChar('}');
84074a628f7SDimitry Andric break;
84174a628f7SDimitry Andric
84274a628f7SDimitry Andric case eFormatVectorOfFloat16:
84374a628f7SDimitry Andric s->PutChar('{');
84474a628f7SDimitry Andric offset =
84574a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
84674a628f7SDimitry Andric item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
84774a628f7SDimitry Andric s->PutChar('}');
84874a628f7SDimitry Andric break;
84974a628f7SDimitry Andric
85074a628f7SDimitry Andric case eFormatVectorOfFloat32:
85174a628f7SDimitry Andric s->PutChar('{');
85274a628f7SDimitry Andric offset =
85374a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
85474a628f7SDimitry Andric item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
85574a628f7SDimitry Andric s->PutChar('}');
85674a628f7SDimitry Andric break;
85774a628f7SDimitry Andric
85874a628f7SDimitry Andric case eFormatVectorOfFloat64:
85974a628f7SDimitry Andric s->PutChar('{');
86074a628f7SDimitry Andric offset =
86174a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
86274a628f7SDimitry Andric item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
86374a628f7SDimitry Andric s->PutChar('}');
86474a628f7SDimitry Andric break;
86574a628f7SDimitry Andric
86674a628f7SDimitry Andric case eFormatVectorOfUInt128:
86774a628f7SDimitry Andric s->PutChar('{');
86874a628f7SDimitry Andric offset =
86974a628f7SDimitry Andric DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
87074a628f7SDimitry Andric item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
87174a628f7SDimitry Andric s->PutChar('}');
87274a628f7SDimitry Andric break;
87374a628f7SDimitry Andric }
87474a628f7SDimitry Andric }
87574a628f7SDimitry Andric
8766f8fc217SDimitry Andric // If anything was printed we want to catch the end of the last line.
8776f8fc217SDimitry Andric // Since we will exit the for loop above before we get a chance to append to
8786f8fc217SDimitry Andric // it normally.
8796f8fc217SDimitry Andric if (offset > line_start_offset) {
8806f8fc217SDimitry Andric if (item_format == eFormatBytesWithASCII) {
8816f8fc217SDimitry Andric s->Printf("%*s",
8826f8fc217SDimitry Andric static_cast<int>(
88374a628f7SDimitry Andric (num_per_line - (offset - line_start_offset)) * 3 + 2),
88474a628f7SDimitry Andric "");
88574a628f7SDimitry Andric DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
88674a628f7SDimitry Andric offset - line_start_offset, SIZE_MAX,
88774a628f7SDimitry Andric LLDB_INVALID_ADDRESS, 0, 0);
88874a628f7SDimitry Andric }
8896f8fc217SDimitry Andric
8906f8fc217SDimitry Andric if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
8916f8fc217SDimitry Andric size_t line_len = offset - line_start_offset;
8926f8fc217SDimitry Andric lldb::addr_t line_base = base_addr + (offset - start_offset - line_len) /
8936f8fc217SDimitry Andric DE.getTargetByteSize();
8946f8fc217SDimitry Andric printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
8956f8fc217SDimitry Andric }
8966f8fc217SDimitry Andric }
8976f8fc217SDimitry Andric
89874a628f7SDimitry Andric return offset; // Return the offset at which we ended up
89974a628f7SDimitry Andric }
90074a628f7SDimitry Andric
DumpHexBytes(Stream * s,const void * src,size_t src_len,uint32_t bytes_per_line,lldb::addr_t base_addr)90174a628f7SDimitry Andric void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,
90274a628f7SDimitry Andric uint32_t bytes_per_line,
90374a628f7SDimitry Andric lldb::addr_t base_addr) {
90474a628f7SDimitry Andric DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
90574a628f7SDimitry Andric DumpDataExtractor(data, s,
90674a628f7SDimitry Andric 0, // Offset into "src"
90774a628f7SDimitry Andric lldb::eFormatBytes, // Dump as hex bytes
90874a628f7SDimitry Andric 1, // Size of each item is 1 for single bytes
90974a628f7SDimitry Andric src_len, // Number of bytes
91074a628f7SDimitry Andric bytes_per_line, // Num bytes per line
91174a628f7SDimitry Andric base_addr, // Base address
91274a628f7SDimitry Andric 0, 0); // Bitfield info
91374a628f7SDimitry Andric }
914