20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseSet.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/BinaryFormat/Magic.h"
26#include "llvm/BinaryFormat/Wasm.h"
27#include "llvm/Support/CheckedArithmetic.h"
28#include "llvm/Support/Endian.h"
29#include "llvm/Support/Format.h"
51 const uint64_t value = data.GetULEB128(&offset);
52 if (value > std::numeric_limits<uint32_t>::max())
53 return llvm::createStringError(
"ULEB exceeds 32 bits");
58static inline llvm::Expected<uint32_t>
59GetULEB32(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
60 const uint64_t value = data.getULEB128(c);
63 if (value > std::numeric_limits<uint32_t>::max())
64 return llvm::createStringError(
"ULEB exceeds 32 bits");
69static inline llvm::Expected<std::string>
70GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
71 llvm::Expected<uint32_t> len =
GetULEB32(data, c);
73 return len.takeError();
75 llvm::SmallVector<uint8_t, 32> str_storage;
76 data.getU8(c, str_storage, *len);
80 return std::string(toStringRef(llvm::ArrayRef(str_storage)));
91 uint8_t opcode = data.
GetU8(&offset);
93 case llvm::wasm::WASM_OPCODE_I32_CONST:
94 case llvm::wasm::WASM_OPCODE_I64_CONST:
97 case llvm::wasm::WASM_OPCODE_GLOBAL_GET:
100 case llvm::wasm::WASM_OPCODE_F32_CONST:
101 case llvm::wasm::WASM_OPCODE_F64_CONST:
105 case llvm::wasm::WASM_OPCODE_REF_NULL:
112 opcode = data.
GetU8(&offset);
113 if (opcode == llvm::wasm::WASM_OPCODE_END)
114 return init_expr_offset;
119 while (opcode != llvm::wasm::WASM_OPCODE_END && data.
ValidOffset(offset))
120 opcode = data.
GetU8(&offset);
129 if (llvm::identify_magic(toStringRef(data)) != llvm::file_magic::wasm_object)
132 const uint8_t *Ptr = data.data() +
sizeof(llvm::wasm::WasmMagic);
134 uint32_t version = llvm::support::endian::read32le(Ptr);
135 return version == llvm::wasm::WasmVersion;
158 if (!extractor_sp || !extractor_sp->HasData()) {
161 LLDB_LOGF(log,
"Failed to create ObjectFileWasm instance for file %s",
165 extractor_sp = std::make_shared<DataExtractor>(data_sp);
169 assert(extractor_sp);
172 "Failed to create ObjectFileWasm instance: invalid Wasm header");
178 if (extractor_sp->GetByteSize() < length) {
182 "Failed to create ObjectFileWasm instance: cannot read file %s",
186 extractor_sp = std::make_shared<DataExtractor>(data_sp);
191 module_sp, extractor_sp, data_offset, file, file_offset, length));
192 ArchSpec spec = objfile_up->GetArchitecture();
193 if (spec && objfile_up->SetModulesArchitecture(spec)) {
195 "%p ObjectFileWasm::CreateInstance() module = %p (%s), file = %s",
196 static_cast<void *
>(objfile_up.get()),
197 static_cast<void *
>(objfile_up->GetModule().get()),
198 objfile_up->GetModule()->GetSpecificationDescription().c_str(),
199 file ? file->
GetPath().c_str() :
"<NULL>");
200 return objfile_up.release();
203 LLDB_LOGF(log,
"Failed to create ObjectFileWasm instance");
214 std::unique_ptr<ObjectFileWasm> objfile_up(
216 ArchSpec spec = objfile_up->GetArchitecture();
217 if (spec && objfile_up->SetModulesArchitecture(spec))
218 return objfile_up.release();
225 const uint32_t kBufferSize = 1024;
228 llvm::DataExtractor data = section_header_data.
GetAsLLVM();
229 llvm::DataExtractor::Cursor c(0);
235 uint8_t section_id = data.getU8(c);
236 uint64_t payload_len = data.getULEB128(c);
238 return !llvm::errorToBool(c.takeError());
240 if (payload_len > std::numeric_limits<uint32_t>::max())
243 if (section_id == llvm::wasm::WASM_SEC_CUSTOM) {
248 llvm::Expected<std::string> sect_name =
GetWasmString(data, c);
251 "failed to parse section name: {0}");
255 if (payload_len < c.tell() - prev_offset)
258 uint32_t section_length = payload_len - (c.tell() - prev_offset);
260 section_id, std::move(*sect_name)});
261 *offset_ptr += (c.tell() + section_length);
262 }
else if (section_id <= llvm::wasm::WASM_SEC_LAST_KNOWN) {
264 static_cast<uint32_t
>(payload_len),
267 *offset_ptr += (c.tell() + payload_len);
302 :
ObjectFile(module_sp, file, offset, length, extractor_sp, data_offset),
311 :
ObjectFile(module_sp, process_sp, header_addr,
342 llvm::DataExtractor data = import_data.
GetAsLLVM();
343 llvm::DataExtractor::Cursor c(0);
345 llvm::Expected<uint32_t> count =
GetULEB32(data, c);
347 return count.takeError();
350 for (uint32_t i = 0; c && i < *count; ++i) {
353 llvm::Expected<std::string> module_name =
GetWasmString(data, c);
355 return llvm::joinErrors(
356 llvm::createStringError(
"failed to parse module name"),
357 module_name.takeError());
358 llvm::Expected<std::string> field_name =
GetWasmString(data, c);
360 return llvm::joinErrors(
361 llvm::createStringError(
"failed to parse field name"),
362 field_name.takeError());
366 const uint8_t kind = data.getU8(c);
368 case llvm::wasm::WASM_EXTERNAL_FUNCTION:
372 case llvm::wasm::WASM_EXTERNAL_GLOBAL:
377 case llvm::wasm::WASM_EXTERNAL_TAG:
381 case llvm::wasm::WASM_EXTERNAL_TABLE:
384 case llvm::wasm::WASM_EXTERNAL_MEMORY: {
386 const uint8_t flags = data.getU8(c);
388 if (flags & llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX)
394 return llvm::joinErrors(
396 llvm::createStringError(
"unknown import kind %u", kind));
401 return c.takeError();
414 const uint32_t local_count = data.
GetULEB128(&offset);
415 for (uint32_t i = 0; i < local_count; ++i) {
419 return offset - locals_start;
422static llvm::Expected<std::vector<WasmFunction>>
426 llvm::Expected<uint32_t> function_count =
GetULEB32(data, offset);
428 return function_count.takeError();
430 std::vector<WasmFunction> functions;
431 functions.reserve(*function_count);
433 for (uint32_t i = 0; i < *function_count; ++i) {
438 llvm::Expected<uint32_t> function_size =
GetULEB32(data, offset);
440 return function_size.takeError();
446 return code_offset.takeError();
448 functions.push_back({offset, *function_size, *code_offset});
450 std::optional<lldb::offset_t> next_offset =
451 llvm::checkedAddUnsigned<lldb::offset_t>(offset, *function_size);
453 return llvm::createStringError(
"function offset overflows 64 bits");
454 offset = *next_offset;
479 llvm::Expected<uint32_t> segment_count =
GetULEB32(data, offset);
481 return segment_count.takeError();
483 std::vector<WasmSegment> segments;
484 segments.reserve(*segment_count);
486 for (uint32_t i = 0; i < *segment_count; ++i) {
487 llvm::Expected<uint32_t> flags =
GetULEB32(data, offset);
489 return flags.takeError();
497 segment.
type = (*flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE)
501 if (*flags & llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) {
503 llvm::Expected<uint32_t> memidx =
GetULEB32(data, offset);
505 return memidx.takeError();
506 segment.memory_index = *memidx;
512 llvm::Expected<uint32_t> segment_size =
GetULEB32(data, offset);
514 return segment_size.takeError();
516 segment.section_offset = offset;
517 segment.size = *segment_size;
518 segments.push_back(segment);
520 std::optional<lldb::offset_t> next_offset =
521 llvm::checkedAddUnsigned<lldb::offset_t>(offset, *segment_size);
523 return llvm::createStringError(
"segment offset overflows 64 bits");
524 offset = *next_offset;
536 llvm::Expected<uint32_t> memory_count =
GetULEB32(data, offset);
538 return memory_count.takeError();
539 if (*memory_count == 0)
540 return llvm::createStringError(
"module declares no linear memory");
545 llvm::Expected<uint32_t> min_pages =
GetULEB32(data, offset);
547 return min_pages.takeError();
549 return static_cast<uint64_t
>(*min_pages) * llvm::wasm::WasmDefaultPageSize;
556 case llvm::wasm::WASM_TYPE_I32:
557 case llvm::wasm::WASM_TYPE_F32:
559 case llvm::wasm::WASM_TYPE_I64:
560 case llvm::wasm::WASM_TYPE_F64:
572 std::optional<uint64_t> value;
574 switch (data.
GetU8(&offset)) {
575 case llvm::wasm::WASM_OPCODE_I32_CONST:
576 value =
static_cast<uint32_t
>(data.
GetSLEB128(&offset));
578 case llvm::wasm::WASM_OPCODE_I64_CONST:
579 value =
static_cast<uint64_t
>(data.
GetSLEB128(&offset));
581 case llvm::wasm::WASM_OPCODE_F32_CONST:
582 value = data.
GetU32(&offset);
584 case llvm::wasm::WASM_OPCODE_F64_CONST:
585 value = data.
GetU64(&offset);
587 case llvm::wasm::WASM_OPCODE_GLOBAL_GET:
588 case llvm::wasm::WASM_OPCODE_REF_NULL:
597 uint8_t opcode = data.
GetU8(&offset);
598 while (opcode != llvm::wasm::WASM_OPCODE_END && data.
ValidOffset(offset))
599 opcode = data.
GetU8(&offset);
600 if (opcode != llvm::wasm::WASM_OPCODE_END)
607static llvm::Expected<std::vector<WasmGlobal>>
611 llvm::Expected<uint32_t> count =
GetULEB32(data, offset);
613 return count.takeError();
616 std::vector<WasmGlobal> globals;
618 for (uint32_t i = 0; i < *count; ++i) {
620 return llvm::createStringError(
621 "global section holds %zu of its %u globals", globals.size(), *count);
628 globals.push_back(global);
634static llvm::Expected<std::vector<Symbol>>
636 DataExtractor &name_data,
const std::vector<WasmFunction> &functions,
637 std::vector<WasmSegment> &segments,
638 const std::vector<WasmGlobal> &globals,
639 uint32_t num_imported_functions, uint32_t num_imported_globals) {
641 llvm::DataExtractor data = name_data.
GetAsLLVM();
642 llvm::DataExtractor::Cursor c(0);
643 std::vector<Symbol> symbols;
644 while (c && c.tell() < data.size()) {
645 const uint8_t type = data.getU8(c);
646 llvm::Expected<uint32_t> size =
GetULEB32(data, c);
648 return size.takeError();
651 case llvm::wasm::WASM_NAMES_FUNCTION: {
652 const uint64_t count = data.getULEB128(c);
653 if (count > std::numeric_limits<uint32_t>::max())
654 return llvm::joinErrors(
656 llvm::createStringError(
"function count overflows uint32_t"));
658 for (uint64_t i = 0; c && i < count; ++i) {
659 llvm::Expected<uint32_t> idx =
GetULEB32(data, c);
661 return idx.takeError();
664 return name.takeError();
665 if (*idx >= num_imported_functions + functions.size())
668 if (*idx < num_imported_functions) {
679 const WasmFunction &func = functions[*idx - num_imported_functions];
688 symbols.back().SetPrologueByteSize(func.
code_offset);
692 case llvm::wasm::WASM_NAMES_DATA_SEGMENT: {
693 llvm::Expected<uint32_t> count =
GetULEB32(data, c);
695 return count.takeError();
696 for (uint32_t i = 0; c && i < *count; ++i) {
697 llvm::Expected<uint32_t> idx =
GetULEB32(data, c);
699 return idx.takeError();
702 return name.takeError();
703 if (*idx >= segments.size())
706 segments[*idx].name = *name;
710 case llvm::wasm::WASM_NAMES_GLOBAL: {
711 llvm::Expected<uint32_t> count =
GetULEB32(data, c);
713 return count.takeError();
714 for (uint32_t i = 0; c && i < *count; ++i) {
715 llvm::Expected<uint32_t> idx =
GetULEB32(data, c);
717 return idx.takeError();
720 return name.takeError();
724 if (*idx < num_imported_globals)
726 const uint32_t global_idx = *idx - num_imported_globals;
727 if (global_idx >= globals.size())
736 global_section_sp, *idx,
743 case llvm::wasm::WASM_NAMES_LOCAL:
745 std::optional<lldb::offset_t> offset =
746 llvm::checkedAddUnsigned<lldb::offset_t>(c.tell(), *size);
748 return llvm::joinErrors(
749 c.takeError(), llvm::createStringError(
"offset overflows 64 bits"));
755 return c.takeError();
766static llvm::Expected<std::vector<WasmExport>>
768 llvm::DataExtractor data = export_data.
GetAsLLVM();
769 llvm::DataExtractor::Cursor c(0);
771 llvm::Expected<uint32_t> count =
GetULEB32(data, c);
773 return count.takeError();
775 std::vector<WasmExport> exports;
776 for (uint32_t i = 0; c && i < *count; ++i) {
779 return name.takeError();
780 const uint8_t kind = data.getU8(c);
781 llvm::Expected<uint32_t> index =
GetULEB32(data, c);
783 return index.takeError();
784 exports.push_back({std::move(*name), kind, *index});
788 return c.takeError();
798 llvm::ArrayRef<WasmGlobal> globals,
799 uint32_t num_imported_globals,
801 llvm::ArrayRef<SectionSP> memory_sections,
802 std::vector<Symbol> &symbols) {
803 llvm::DenseSet<uint32_t> named_globals;
804 if (global_section_sp)
805 for (
const Symbol &symbol : symbols)
806 if (symbol.GetAddressRef().GetSection() == global_section_sp)
807 named_globals.insert(symbol.GetAddressRef().GetOffset());
810 if (exp.kind != llvm::wasm::WASM_EXTERNAL_GLOBAL ||
811 exp.index < num_imported_globals || named_globals.contains(exp.index))
813 const uint32_t global_idx = exp.index - num_imported_globals;
814 if (global_idx >= globals.size())
817 const WasmGlobal &global = globals[global_idx];
819 (global.
value_type != llvm::wasm::WASM_TYPE_I32 &&
820 global.
value_type != llvm::wasm::WASM_TYPE_I64))
825 llvm::find_if(memory_sections, [addr](
const SectionSP §ion) {
826 return section->ContainsFileAddress(addr);
828 if (section_sp == memory_sections.end())
836 *section_sp, addr - (*section_sp)->GetFileAddress(),
853 if (Name.consume_front(
".debug_") || Name.consume_front(
".zdebug_"))
862 return llvm::StringSwitch<SectionType>(Name)
868std::optional<ObjectFileWasm::section_info>
871 if (sect_info.id == section_id)
877std::optional<ObjectFileWasm::section_info>
880 if (sect_info.name == section_name)
900 std::string section_name;
901 offset_t file_offset = sect_info.offset & 0xffffffff;
902 addr_t vm_addr = sect_info.offset;
903 size_t vm_size = sect_info.size;
905 if (llvm::wasm::WASM_SEC_CODE == sect_info.id) {
907 section_name =
"code";
918 section_name = sect_info.name;
925 SectionSP section_sp = std::make_shared<Section>(
944 std::vector<WasmFunction> functions;
945 std::vector<WasmSegment> segments;
948 if (std::optional<section_info> info =
951 llvm::Expected<std::vector<WasmFunction>> maybe_functions =
953 if (!maybe_functions) {
955 "Failed to parse Wasm code section: {0}");
957 functions = *maybe_functions;
963 bool imports_parsed =
true;
964 if (std::optional<section_info> info =
967 llvm::Expected<WasmImports> imports =
ParseImports(import_data);
970 "Failed to parse Wasm import section: {0}");
971 imports_parsed =
false;
979 if (std::optional<section_info> info =
982 llvm::Expected<std::vector<WasmGlobal>> globals =
ParseGlobals(global_data);
985 "Failed to parse Wasm global section: {0}");
992 std::optional<section_info> data_info =
996 llvm::Expected<std::vector<WasmSegment>> maybe_segments =
998 if (!maybe_segments) {
1000 "Failed to parse Wasm data section: {0}");
1002 segments = *maybe_segments;
1011 global_section_sp = std::make_shared<Section>(
1020 unified_section_list.
AddSection(global_section_sp);
1025 llvm::Expected<std::vector<Symbol>> symbols =
ParseNames(
1027 global_section_sp, names_data, functions, segments,
m_globals,
1031 "Failed to parse Wasm names: {0}");
1039 std::vector<SectionSP> memory_sections;
1043 if (segment.memory_index != 0) {
1045 "Skipping segment {}: non-zero memory index is "
1046 "currently unsupported",
1052 LLDB_LOG(log,
"Skipping segment {}: unsupported init expression",
1060 ? segment.init_expr_offset
1061 : data_info->offset + segment.section_offset;
1063 data_info->GetFileOffset() + segment.GetFileOffset();
1064 SectionSP segment_sp = std::make_shared<Section>(
1076 GetModule()->GetSectionList()->AddSection(segment_sp);
1079 memory_sections.push_back(segment_sp);
1080 static_data_end = std::max(static_data_end, file_vm_addr + segment.size);
1089 if (std::optional<section_info> mem_info =
1095 "Failed to parse Wasm memory section: {0}");
1096 }
else if (*memory_size > static_data_end) {
1097 SectionSP bss_sp = std::make_shared<Section>(
1101 *memory_size - static_data_end,
1106 GetModule()->GetSectionList()->AddSection(bss_sp);
1107 memory_sections.push_back(bss_sp);
1113 if (!imports_parsed)
1116 if (std::optional<section_info> info =
1119 llvm::Expected<std::vector<WasmExport>> exports =
ParseExports(export_data);
1122 "Failed to parse Wasm export section: {0}");
1125 global_section_sp, memory_sections,
m_symbols);
1149 uint8_t bytes[
sizeof(uint64_t)];
1151 std::memcpy(dst, bytes, dst_len);
1156 bool value_is_offset) {
1182 size_t num_loaded_sections = 0;
1187 const size_t num_sections = section_list->
GetSize();
1188 for (
size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
1191 switch (section_sp->GetType()) {
1207 section_load_addr = load_address | section_sp->GetFileOffset();
1211 ++num_loaded_sections;
1214 return num_loaded_sections > 0;
1221 size = std::min(
static_cast<uint64_t
>(size),
GetByteSize() - offset);
1228 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
1230 size_t bytes_read = process_sp->ReadMemory(
1231 offset, data_up->GetBytes(), data_up->GetByteSize(), readmem_error);
1232 if (bytes_read > 0) {
1237 size = std::min(
static_cast<uint64_t
>(size),
1254 static constexpr llvm::StringLiteral g_sect_name_build_id(
"build_id");
1256 if (g_sect_name_build_id != sect_info.name)
1261 llvm::DataExtractor data = section_data.
GetAsLLVM();
1262 llvm::DataExtractor::Cursor c(0);
1263 llvm::Expected<uint32_t> length =
GetULEB32(data, c);
1266 "failed to parse the build id length: {0}");
1269 llvm::SmallVector<uint8_t, 32>
id(*length, 0);
1270 data.getU8(c,
id.data(),
id.size());
1273 "failed to parse the build id: {0}");
1284 static constexpr llvm::StringLiteral g_sect_name_external_debug_info(
1285 "external_debug_info");
1288 if (g_sect_name_external_debug_info == sect_info.name) {
1289 const uint32_t kBufferSize = 1024;
1293 llvm::DataExtractor data = section_header_data.
GetAsLLVM();
1294 llvm::DataExtractor::Cursor c(0);
1295 llvm::Expected<std::string> symbols_url =
GetWasmString(data, c);
1297 llvm::consumeError(symbols_url.takeError());
1298 return std::nullopt;
1303 return std::nullopt;
1311 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1314 ostream << static_cast<void *>(
this) <<
": ";
1316 ostream <<
"ObjectFileWasm, file = '";
1318 ostream <<
"', arch = ";
1333 ostream << llvm::left_justify(sh.
name, 16) <<
" "
1334 << llvm::format_hex(sh.
offset, 10) <<
" "
1335 << llvm::format_hex(sh.
size, 10) <<
" " << llvm::format_hex(sh.
id, 6)
1340 ostream <<
"Section Headers\n";
1341 ostream <<
"IDX name addr size id\n";
1342 ostream <<
"==== ---------------- ---------- ---------- ------\n";
1347 ostream <<
"[" << llvm::format_decimal(idx, 2) <<
"] ";
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
#define LLDB_LOG_ERROR(log, error,...)
static SectionType GetSectionTypeFromName(llvm::StringRef Name)
static void AddExportedDataSymbols(llvm::ArrayRef< WasmExport > exports, llvm::ArrayRef< WasmGlobal > globals, uint32_t num_imported_globals, const SectionSP &global_section_sp, llvm::ArrayRef< SectionSP > memory_sections, std::vector< Symbol > &symbols)
Adds to symbols a data symbol for each export that stands for a variable in linear memory.
static std::optional< uint32_t > GetWasmValueTypeSize(uint8_t type)
Size in bytes of a WebAssembly value type, or nothing for the types whose values cannot be read.
static lldb::offset_t GetWasmOffsetFromInitExpr(DataExtractor &data, lldb::offset_t &offset)
An "init expr" refers to a constant expression used to determine the initial value of certain element...
static llvm::Expected< std::vector< WasmGlobal > > ParseGlobals(DataExtractor &data)
Parse the module's own globals, which start at the number of imported ones.
static llvm::Expected< std::string > GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c)
Helper to read a Wasm string, whcih is encoded as a vector of UTF-8 codes.
static llvm::Expected< uint32_t > GetULEB32(DataExtractor &data, lldb::offset_t &offset)
Helper to read a 32-bit ULEB using LLDB's DataExtractor.
static llvm::Expected< WasmImports > ParseImports(DataExtractor &import_data)
static llvm::Expected< std::vector< WasmExport > > ParseExports(DataExtractor &export_data)
static llvm::Expected< uint32_t > GetFunctionCodeOffset(DataExtractor &data, lldb::offset_t offset)
Get the offset in the function to the first instruction.
static llvm::Expected< std::vector< WasmFunction > > ParseFunctions(DataExtractor &data)
static llvm::Expected< std::vector< Symbol > > ParseNames(SectionSP code_section_sp, SectionSP global_section_sp, DataExtractor &name_data, const std::vector< WasmFunction > &functions, std::vector< WasmSegment > &segments, const std::vector< WasmGlobal > &globals, uint32_t num_imported_functions, uint32_t num_imported_globals)
static bool ValidateModuleHeader(llvm::ArrayRef< uint8_t > data)
Checks whether the data buffer starts with a valid Wasm module header.
static SectionType GetSegmentTypeFromName(llvm::StringRef Name)
A section attribute on a data variable lands in a named data segment on wasm, not a top-level custom ...
static const uint32_t kWasmHeaderSize
static llvm::Expected< uint64_t > ParseMemoryMinSize(DataExtractor &data)
Parse the minimum size in bytes of the module's first linear memory.
static constexpr lldb::addr_t kWasmGlobalFileAddress
File address the synthetic global section is based at.
static std::optional< uint64_t > ParseGlobalInitValue(DataExtractor &data, lldb::offset_t &offset)
Parse the init expr that gives a global its initial value.
static llvm::Expected< std::vector< WasmSegment > > ParseData(DataExtractor &data)
#define LLDB_PLUGIN_DEFINE(PluginName)
An architecture specification class.
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
void Append(const ModuleSpec &spec)
std::unique_ptr< lldb_private::SectionList > m_sections_up
static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, uint64_t Offset)
const lldb::addr_t m_memory_addr
Set if the object file only exists in memory.
static lldb::SectionType GetDWARFSectionTypeFromName(llvm::StringRef name)
Parses the section type from a section name for DWARF sections.
DataExtractorNSP m_data_nsp
The data for this object file so things can be parsed lazily.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
ObjectFile(const lldb::ModuleSP &module_sp, const FileSpec *file_spec_ptr, lldb::offset_t file_offset, lldb::offset_t length, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset)
Construct with a parent module, offset, and header data.
bool IsInMemory() const
Returns true if the object file exists only in memory.
lldb::ProcessWP m_process_wp
virtual size_t ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len)
virtual lldb::addr_t GetByteSize() const
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
size_t AddSection(const lldb::SectionSP §ion_sp)
void Dump(llvm::raw_ostream &s, unsigned indent, Target *target, bool show_header, uint32_t depth) const
lldb::SectionSP GetSectionAtIndex(size_t idx) const
lldb::SectionType GetType() const
A stream class that can stream formatted output to a file.
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
unsigned GetIndentLevel() const
Get the current indentation level.
uint32_t AddSymbol(const Symbol &symbol)
bool SetSectionLoadAddress(const lldb::SectionSP §ion, lldb::addr_t load_addr, bool warn_multiple=false)
Represents UUID's of various sizes.
Generic Wasm object file reader.
ArchSpec GetArchitecture() override
Get the ArchSpec for this object file.
std::optional< FileSpec > GetExternalDebugInfoFileSpec()
A Wasm module that has external DWARF debug information should contain a custom section named "extern...
size_t ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len) override
A global has no bytes in the module to read, so serve its initial value when there is no process to a...
bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, bool value_is_offset) override
Sets the load address for an entire module, assuming a rigid slide of sections, if possible in the im...
bool DecodeNextSection(lldb::offset_t *offset_ptr)
Wasm section decoding routines.
lldb::ByteOrder GetByteOrder() const override
Gets whether endian swapping should occur when extracting data from this object file.
void CreateSections(SectionList &unified_section_list) override
ObjectFileWasm(const lldb::ModuleSP &module_sp, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length)
std::optional< section_info > GetSectionInfo(uint32_t section_id)
void Dump(Stream *s) override
Dump a description of this object to a Stream.
static llvm::StringRef GetPluginNameStatic()
std::vector< section_info > m_sect_infos
UUID GetUUID() override
Gets the UUID for this object file.
void DumpSectionHeader(llvm::raw_ostream &ostream, const section_info &sh)
Wasm section header dump routines.
void DumpSectionHeaders(llvm::raw_ostream &ostream)
static ObjectFile * CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length)
static char ID
LLVM RTTI support.
std::vector< Symbol > m_symbols
void ParseSymtab(lldb_private::Symtab &symtab) override
Parse the symbol table into the provides symbol table object.
static ModuleSpecList GetModuleSpecifications(const FileSpec &file, lldb::DataExtractorSP &extractor_sp, lldb::offset_t file_offset, lldb::offset_t length)
uint32_t GetAddressByteSize() const override
Gets the address size in bytes for the current object file.
uint32_t m_num_imported_globals
static ObjectFile * CreateMemoryInstance(const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr)
std::vector< WasmGlobal > m_globals
bool ParseHeader() override
ObjectFile Protocol.
uint32_t m_num_imported_functions
static const char * GetPluginDescriptionStatic()
DataExtractor ReadImageData(lldb::offset_t offset, uint32_t size)
Read a range of bytes from the Wasm module.
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_OFFSET
static constexpr uint64_t kWasmAddressTypeMask
WasmAddressType
Each WebAssembly module has separate address spaces for Code and Memory.
static constexpr uint32_t kWasmAddressTypeShift
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eSectionTypeLLDBFormatters
@ eSectionTypeLLDBTypeSummaries
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
std::shared_ptr< lldb_private::Module > ModuleSP
lldb::offset_t section_offset
Offset from the section to the start of the function.
uint32_t code_offset
Offset from section_offset to the first instruction in the function, past the local variable declarat...
uint32_t size
Function size, which includes the function header, but not the size ULEB that proceeds it.
The number of imports of each kind.
lldb::offset_t section_offset
lldb::offset_t GetFileOffset() const
lldb::offset_t init_expr_offset
A global declared by the module itself.
std::optional< uint32_t > size
Size of the global's value type, which bounds what a read can produce.
std::optional< uint64_t > init_expr_value
Value the global is initialized with, when the initializer is a constant.