20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/BinaryFormat/Magic.h"
24#include "llvm/BinaryFormat/Wasm.h"
25#include "llvm/Support/Endian.h"
26#include "llvm/Support/Format.h"
36 sizeof(
llvm::wasm::WasmMagic) + sizeof(
llvm::wasm::WasmVersion);
43 if (llvm::identify_magic(toStringRef(data_sp->GetData())) !=
44 llvm::file_magic::wasm_object)
47 const uint8_t *Ptr = data_sp->GetBytes() +
sizeof(llvm::wasm::WasmMagic);
49 uint32_t version = llvm::support::endian::read32le(Ptr);
50 return version == llvm::wasm::WasmVersion;
53static std::optional<ConstString>
54GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
58 uint64_t len = data.getULEB128(c);
60 consumeError(c.takeError());
64 if (len >= (uint64_t(1) << 32)) {
68 llvm::SmallVector<uint8_t, 32> str_storage;
69 data.getU8(c, str_storage, len);
71 consumeError(c.takeError());
75 llvm::StringRef str = toStringRef(llvm::ArrayRef(str_storage));
100 LLDB_LOGF(log,
"Failed to create ObjectFileWasm instance for file %s",
110 "Failed to create ObjectFileWasm instance: invalid Wasm header");
116 if (data_sp->GetByteSize() < length) {
120 "Failed to create ObjectFileWasm instance: cannot read file %s",
128 module_sp, data_sp, data_offset, file, file_offset, length));
129 ArchSpec spec = objfile_up->GetArchitecture();
130 if (spec && objfile_up->SetModulesArchitecture(spec)) {
132 "%p ObjectFileWasm::CreateInstance() module = %p (%s), file = %s",
133 static_cast<void *
>(objfile_up.get()),
134 static_cast<void *
>(objfile_up->GetModule().get()),
135 objfile_up->GetModule()->GetSpecificationDescription().c_str(),
136 file ? file->
GetPath().c_str() :
"<NULL>");
137 return objfile_up.release();
140 LLDB_LOGF(log,
"Failed to create ObjectFileWasm instance");
151 std::unique_ptr<ObjectFileWasm> objfile_up(
153 ArchSpec spec = objfile_up->GetArchitecture();
154 if (spec && objfile_up->SetModulesArchitecture(spec))
155 return objfile_up.release();
162 const uint32_t kBufferSize = 1024;
165 llvm::DataExtractor data = section_header_data.
GetAsLLVM();
166 llvm::DataExtractor::Cursor c(0);
172 uint8_t section_id = data.getU8(c);
173 uint64_t payload_len = data.getULEB128(c);
175 return !llvm::errorToBool(c.takeError());
177 if (payload_len >= (uint64_t(1) << 32))
180 if (section_id == llvm::wasm::WASM_SEC_CUSTOM) {
185 std::optional<ConstString> sect_name =
GetWasmString(data, c);
189 if (payload_len < c.tell() - prev_offset)
192 uint32_t section_length = payload_len - (c.tell() - prev_offset);
194 section_id, *sect_name});
195 *offset_ptr += (c.tell() + section_length);
196 }
else if (section_id <= llvm::wasm::WASM_SEC_LAST_KNOWN) {
198 static_cast<uint32_t
>(payload_len),
200 *offset_ptr += (c.tell() + payload_len);
234 :
ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
235 m_arch(
"wasm32-unknown-unknown-wasm") {
243 :
ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
244 m_arch(
"wasm32-unknown-unknown-wasm") {}
254 if (Name.consume_front(
".debug_") || Name.consume_front(
".zdebug_")) {
255 return llvm::StringSwitch<SectionType>(Name)
303 offset_t file_offset = sect_info.offset & 0xffffffff;
304 addr_t vm_addr = file_offset;
305 size_t vm_size = sect_info.size;
307 if (llvm::wasm::WASM_SEC_CODE == sect_info.id) {
320 section_name = sect_info.name;
347 bool value_is_offset) {
373 size_t num_loaded_sections = 0;
378 const size_t num_sections = section_list->
GetSize();
379 for (
size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
382 section_sp, load_address | section_sp->GetFileOffset())) {
383 ++num_loaded_sections;
387 return num_loaded_sections > 0;
394 size = std::min(
static_cast<uint64_t
>(size),
GetByteSize() - offset);
401 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
403 size_t bytes_read = process_sp->ReadMemory(
404 offset, data_up->GetBytes(), data_up->GetByteSize(), readmem_error);
405 if (bytes_read > 0) {
407 data.
SetData(buffer_sp, 0, buffer_sp->GetByteSize());
417 static ConstString g_sect_name_external_debug_info(
"external_debug_info");
420 if (g_sect_name_external_debug_info == sect_info.name) {
421 const uint32_t kBufferSize = 1024;
424 llvm::DataExtractor data = section_header_data.
GetAsLLVM();
425 llvm::DataExtractor::Cursor c(0);
426 std::optional<ConstString> symbols_url =
GetWasmString(data, c);
428 return FileSpec(symbols_url->GetStringRef());
439 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
442 ostream << static_cast<void *>(
this) <<
": ";
444 ostream <<
"ObjectFileWasm, file = '";
446 ostream <<
"', arch = ";
462 << llvm::format_hex(sh.
offset, 10) <<
" "
463 << llvm::format_hex(sh.
size, 10) <<
" " << llvm::format_hex(sh.
id, 6)
468 ostream <<
"Section Headers\n";
469 ostream <<
"IDX name addr size id\n";
470 ostream <<
"==== ---------------- ---------- ---------- ------\n";
475 ostream <<
"[" << llvm::format_decimal(idx, 2) <<
"] ";
#define LLDB_LOGF(log,...)
static SectionType GetSectionTypeFromName(llvm::StringRef Name)
static bool ValidateModuleHeader(const DataBufferSP &data_sp)
Checks whether the data buffer starts with a valid Wasm module header.
static const uint32_t kWasmHeaderSize
static std::optional< ConstString > GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c)
#define LLDB_PLUGIN_DEFINE(PluginName)
An architecture specification class.
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
A uniqued constant string class.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
void Dump(llvm::raw_ostream &s) const
Dump this object to a Stream.
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
void Append(const ModuleSpec &spec)
A plug-in interface definition class for object file parsers.
DataExtractor m_data
The data for this object file so things can be parsed lazily.
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.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
bool IsInMemory() const
Returns true if the object file exists only in memory.
lldb::ProcessWP m_process_wp
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
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.
bool SetSectionLoadAddress(const lldb::SectionSP §ion, lldb::addr_t load_addr, bool warn_multiple=false)
Generic Wasm object file reader.
ObjectFileWasm(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length)
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...
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
void DumpSectionHeader(llvm::raw_ostream &ostream, const section_info_t &sh)
Wasm section header dump routines.
void Dump(Stream *s) override
Dump a description of this object to a Stream.
static llvm::StringRef GetPluginNameStatic()
static size_t GetModuleSpecifications(const FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, ModuleSpecList &specs)
void DumpSectionHeaders(llvm::raw_ostream &ostream)
std::vector< section_info_t > m_sect_infos
static ObjectFile * CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length)
static char ID
LLVM RTTI support.
void ParseSymtab(lldb_private::Symtab &symtab) override
Parse the symbol table into the provides symbol table object.
uint32_t GetAddressByteSize() const override
Gets the address size in bytes for the current object file.
static ObjectFile * CreateMemoryInstance(const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr)
bool ParseHeader() override
ObjectFile Protocol.
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
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
@ eSectionTypeDWARFDebugStrOffsets
@ eSectionTypeDWARFDebugPubNames
@ eSectionTypeDWARFDebugLocDwo
@ eSectionTypeDWARFDebugFrame
@ eSectionTypeDWARFDebugLocLists
DWARF v5 .debug_loclists.
@ eSectionTypeDWARFDebugTypes
DWARF .debug_types section.
@ eSectionTypeDWARFDebugMacInfo
@ eSectionTypeDWARFDebugNames
DWARF v5 .debug_names.
@ eSectionTypeDWARFDebugRngLists
DWARF v5 .debug_rnglists.
@ eSectionTypeDWARFDebugStrOffsetsDwo
@ eSectionTypeDWARFDebugMacro
@ eSectionTypeDWARFDebugInfo
@ eSectionTypeDWARFDebugTypesDwo
@ eSectionTypeDWARFDebugRanges
@ eSectionTypeDWARFDebugRngListsDwo
@ eSectionTypeDWARFDebugLine
@ eSectionTypeDWARFDebugPubTypes
@ eSectionTypeDWARFDebugTuIndex
@ eSectionTypeDWARFDebugStr
@ eSectionTypeDWARFDebugLineStr
DWARF v5 .debug_line_str.
@ eSectionTypeDWARFDebugLoc
@ eSectionTypeDWARFDebugCuIndex
@ eSectionTypeDWARFDebugAranges
@ eSectionTypeDWARFDebugAbbrevDwo
@ eSectionTypeDWARFDebugStrDwo
@ eSectionTypeDWARFDebugAbbrev
@ eSectionTypeDWARFDebugLocListsDwo
@ eSectionTypeDWARFDebugInfoDwo
@ eSectionTypeDWARFDebugAddr
std::shared_ptr< lldb_private::Module > ModuleSP