xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
15ffd83dbSDimitry Andric //===-- ObjectFileWasm.cpp ------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
95ffd83dbSDimitry Andric #include "ObjectFileWasm.h"
105ffd83dbSDimitry Andric #include "lldb/Core/Module.h"
115ffd83dbSDimitry Andric #include "lldb/Core/ModuleSpec.h"
125ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h"
135ffd83dbSDimitry Andric #include "lldb/Core/Section.h"
145ffd83dbSDimitry Andric #include "lldb/Target/Process.h"
155ffd83dbSDimitry Andric #include "lldb/Target/SectionLoadList.h"
165ffd83dbSDimitry Andric #include "lldb/Target/Target.h"
175ffd83dbSDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
195ffd83dbSDimitry Andric #include "lldb/Utility/Log.h"
205ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
215ffd83dbSDimitry Andric #include "llvm/ADT/SmallVector.h"
225ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
235ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Magic.h"
245ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
255ffd83dbSDimitry Andric #include "llvm/Support/Endian.h"
265ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
27*bdd1243dSDimitry Andric #include <optional>
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric using namespace lldb;
305ffd83dbSDimitry Andric using namespace lldb_private;
315ffd83dbSDimitry Andric using namespace lldb_private::wasm;
325ffd83dbSDimitry Andric 
335ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ObjectFileWasm)
345ffd83dbSDimitry Andric 
355ffd83dbSDimitry Andric static const uint32_t kWasmHeaderSize =
365ffd83dbSDimitry Andric     sizeof(llvm::wasm::WasmMagic) + sizeof(llvm::wasm::WasmVersion);
375ffd83dbSDimitry Andric 
385ffd83dbSDimitry Andric /// Checks whether the data buffer starts with a valid Wasm module header.
ValidateModuleHeader(const DataBufferSP & data_sp)395ffd83dbSDimitry Andric static bool ValidateModuleHeader(const DataBufferSP &data_sp) {
405ffd83dbSDimitry Andric   if (!data_sp || data_sp->GetByteSize() < kWasmHeaderSize)
415ffd83dbSDimitry Andric     return false;
425ffd83dbSDimitry Andric 
435ffd83dbSDimitry Andric   if (llvm::identify_magic(toStringRef(data_sp->GetData())) !=
445ffd83dbSDimitry Andric       llvm::file_magic::wasm_object)
455ffd83dbSDimitry Andric     return false;
465ffd83dbSDimitry Andric 
4781ad6265SDimitry Andric   const uint8_t *Ptr = data_sp->GetBytes() + sizeof(llvm::wasm::WasmMagic);
485ffd83dbSDimitry Andric 
495ffd83dbSDimitry Andric   uint32_t version = llvm::support::endian::read32le(Ptr);
505ffd83dbSDimitry Andric   return version == llvm::wasm::WasmVersion;
515ffd83dbSDimitry Andric }
525ffd83dbSDimitry Andric 
53*bdd1243dSDimitry Andric static std::optional<ConstString>
GetWasmString(llvm::DataExtractor & data,llvm::DataExtractor::Cursor & c)545ffd83dbSDimitry Andric GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
555ffd83dbSDimitry Andric   // A Wasm string is encoded as a vector of UTF-8 codes.
565ffd83dbSDimitry Andric   // Vectors are encoded with their u32 length followed by the element
575ffd83dbSDimitry Andric   // sequence.
585ffd83dbSDimitry Andric   uint64_t len = data.getULEB128(c);
595ffd83dbSDimitry Andric   if (!c) {
605ffd83dbSDimitry Andric     consumeError(c.takeError());
61*bdd1243dSDimitry Andric     return std::nullopt;
625ffd83dbSDimitry Andric   }
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric   if (len >= (uint64_t(1) << 32)) {
65*bdd1243dSDimitry Andric     return std::nullopt;
665ffd83dbSDimitry Andric   }
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric   llvm::SmallVector<uint8_t, 32> str_storage;
695ffd83dbSDimitry Andric   data.getU8(c, str_storage, len);
705ffd83dbSDimitry Andric   if (!c) {
715ffd83dbSDimitry Andric     consumeError(c.takeError());
72*bdd1243dSDimitry Andric     return std::nullopt;
735ffd83dbSDimitry Andric   }
745ffd83dbSDimitry Andric 
75*bdd1243dSDimitry Andric   llvm::StringRef str = toStringRef(llvm::ArrayRef(str_storage));
765ffd83dbSDimitry Andric   return ConstString(str);
775ffd83dbSDimitry Andric }
785ffd83dbSDimitry Andric 
795ffd83dbSDimitry Andric char ObjectFileWasm::ID;
805ffd83dbSDimitry Andric 
Initialize()815ffd83dbSDimitry Andric void ObjectFileWasm::Initialize() {
825ffd83dbSDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
835ffd83dbSDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
845ffd83dbSDimitry Andric                                 CreateMemoryInstance, GetModuleSpecifications);
855ffd83dbSDimitry Andric }
865ffd83dbSDimitry Andric 
Terminate()875ffd83dbSDimitry Andric void ObjectFileWasm::Terminate() {
885ffd83dbSDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
895ffd83dbSDimitry Andric }
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric ObjectFile *
CreateInstance(const ModuleSP & module_sp,DataBufferSP data_sp,offset_t data_offset,const FileSpec * file,offset_t file_offset,offset_t length)9281ad6265SDimitry Andric ObjectFileWasm::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
935ffd83dbSDimitry Andric                                offset_t data_offset, const FileSpec *file,
945ffd83dbSDimitry Andric                                offset_t file_offset, offset_t length) {
9581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Object);
965ffd83dbSDimitry Andric 
975ffd83dbSDimitry Andric   if (!data_sp) {
985ffd83dbSDimitry Andric     data_sp = MapFileData(*file, length, file_offset);
995ffd83dbSDimitry Andric     if (!data_sp) {
1005ffd83dbSDimitry Andric       LLDB_LOGF(log, "Failed to create ObjectFileWasm instance for file %s",
1015ffd83dbSDimitry Andric                 file->GetPath().c_str());
1025ffd83dbSDimitry Andric       return nullptr;
1035ffd83dbSDimitry Andric     }
1045ffd83dbSDimitry Andric     data_offset = 0;
1055ffd83dbSDimitry Andric   }
1065ffd83dbSDimitry Andric 
1075ffd83dbSDimitry Andric   assert(data_sp);
1085ffd83dbSDimitry Andric   if (!ValidateModuleHeader(data_sp)) {
1095ffd83dbSDimitry Andric     LLDB_LOGF(log,
1105ffd83dbSDimitry Andric               "Failed to create ObjectFileWasm instance: invalid Wasm header");
1115ffd83dbSDimitry Andric     return nullptr;
1125ffd83dbSDimitry Andric   }
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   // Update the data to contain the entire file if it doesn't contain it
1155ffd83dbSDimitry Andric   // already.
1165ffd83dbSDimitry Andric   if (data_sp->GetByteSize() < length) {
1175ffd83dbSDimitry Andric     data_sp = MapFileData(*file, length, file_offset);
1185ffd83dbSDimitry Andric     if (!data_sp) {
1195ffd83dbSDimitry Andric       LLDB_LOGF(log,
1205ffd83dbSDimitry Andric                 "Failed to create ObjectFileWasm instance: cannot read file %s",
1215ffd83dbSDimitry Andric                 file->GetPath().c_str());
1225ffd83dbSDimitry Andric       return nullptr;
1235ffd83dbSDimitry Andric     }
1245ffd83dbSDimitry Andric     data_offset = 0;
1255ffd83dbSDimitry Andric   }
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric   std::unique_ptr<ObjectFileWasm> objfile_up(new ObjectFileWasm(
1285ffd83dbSDimitry Andric       module_sp, data_sp, data_offset, file, file_offset, length));
1295ffd83dbSDimitry Andric   ArchSpec spec = objfile_up->GetArchitecture();
1305ffd83dbSDimitry Andric   if (spec && objfile_up->SetModulesArchitecture(spec)) {
1315ffd83dbSDimitry Andric     LLDB_LOGF(log,
1325ffd83dbSDimitry Andric               "%p ObjectFileWasm::CreateInstance() module = %p (%s), file = %s",
1335ffd83dbSDimitry Andric               static_cast<void *>(objfile_up.get()),
1345ffd83dbSDimitry Andric               static_cast<void *>(objfile_up->GetModule().get()),
1355ffd83dbSDimitry Andric               objfile_up->GetModule()->GetSpecificationDescription().c_str(),
1365ffd83dbSDimitry Andric               file ? file->GetPath().c_str() : "<NULL>");
1375ffd83dbSDimitry Andric     return objfile_up.release();
1385ffd83dbSDimitry Andric   }
1395ffd83dbSDimitry Andric 
1405ffd83dbSDimitry Andric   LLDB_LOGF(log, "Failed to create ObjectFileWasm instance");
1415ffd83dbSDimitry Andric   return nullptr;
1425ffd83dbSDimitry Andric }
1435ffd83dbSDimitry Andric 
CreateMemoryInstance(const ModuleSP & module_sp,WritableDataBufferSP data_sp,const ProcessSP & process_sp,addr_t header_addr)1445ffd83dbSDimitry Andric ObjectFile *ObjectFileWasm::CreateMemoryInstance(const ModuleSP &module_sp,
14581ad6265SDimitry Andric                                                  WritableDataBufferSP data_sp,
1465ffd83dbSDimitry Andric                                                  const ProcessSP &process_sp,
1475ffd83dbSDimitry Andric                                                  addr_t header_addr) {
1485ffd83dbSDimitry Andric   if (!ValidateModuleHeader(data_sp))
1495ffd83dbSDimitry Andric     return nullptr;
1505ffd83dbSDimitry Andric 
1515ffd83dbSDimitry Andric   std::unique_ptr<ObjectFileWasm> objfile_up(
1525ffd83dbSDimitry Andric       new ObjectFileWasm(module_sp, data_sp, process_sp, header_addr));
1535ffd83dbSDimitry Andric   ArchSpec spec = objfile_up->GetArchitecture();
1545ffd83dbSDimitry Andric   if (spec && objfile_up->SetModulesArchitecture(spec))
1555ffd83dbSDimitry Andric     return objfile_up.release();
1565ffd83dbSDimitry Andric   return nullptr;
1575ffd83dbSDimitry Andric }
1585ffd83dbSDimitry Andric 
DecodeNextSection(lldb::offset_t * offset_ptr)1595ffd83dbSDimitry Andric bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) {
1605ffd83dbSDimitry Andric   // Buffer sufficient to read a section header and find the pointer to the next
1615ffd83dbSDimitry Andric   // section.
1625ffd83dbSDimitry Andric   const uint32_t kBufferSize = 1024;
1635ffd83dbSDimitry Andric   DataExtractor section_header_data = ReadImageData(*offset_ptr, kBufferSize);
1645ffd83dbSDimitry Andric 
1655ffd83dbSDimitry Andric   llvm::DataExtractor data = section_header_data.GetAsLLVM();
1665ffd83dbSDimitry Andric   llvm::DataExtractor::Cursor c(0);
1675ffd83dbSDimitry Andric 
1685ffd83dbSDimitry Andric   // Each section consists of:
1695ffd83dbSDimitry Andric   // - a one-byte section id,
1705ffd83dbSDimitry Andric   // - the u32 size of the contents, in bytes,
1715ffd83dbSDimitry Andric   // - the actual contents.
1725ffd83dbSDimitry Andric   uint8_t section_id = data.getU8(c);
1735ffd83dbSDimitry Andric   uint64_t payload_len = data.getULEB128(c);
1745ffd83dbSDimitry Andric   if (!c)
1755ffd83dbSDimitry Andric     return !llvm::errorToBool(c.takeError());
1765ffd83dbSDimitry Andric 
1775ffd83dbSDimitry Andric   if (payload_len >= (uint64_t(1) << 32))
1785ffd83dbSDimitry Andric     return false;
1795ffd83dbSDimitry Andric 
1805ffd83dbSDimitry Andric   if (section_id == llvm::wasm::WASM_SEC_CUSTOM) {
1815ffd83dbSDimitry Andric     // Custom sections have the id 0. Their contents consist of a name
1825ffd83dbSDimitry Andric     // identifying the custom section, followed by an uninterpreted sequence
1835ffd83dbSDimitry Andric     // of bytes.
1845ffd83dbSDimitry Andric     lldb::offset_t prev_offset = c.tell();
185*bdd1243dSDimitry Andric     std::optional<ConstString> sect_name = GetWasmString(data, c);
1865ffd83dbSDimitry Andric     if (!sect_name)
1875ffd83dbSDimitry Andric       return false;
1885ffd83dbSDimitry Andric 
1895ffd83dbSDimitry Andric     if (payload_len < c.tell() - prev_offset)
1905ffd83dbSDimitry Andric       return false;
1915ffd83dbSDimitry Andric 
1925ffd83dbSDimitry Andric     uint32_t section_length = payload_len - (c.tell() - prev_offset);
1935ffd83dbSDimitry Andric     m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), section_length,
1945ffd83dbSDimitry Andric                                         section_id, *sect_name});
1955ffd83dbSDimitry Andric     *offset_ptr += (c.tell() + section_length);
19681ad6265SDimitry Andric   } else if (section_id <= llvm::wasm::WASM_SEC_LAST_KNOWN) {
1975ffd83dbSDimitry Andric     m_sect_infos.push_back(section_info{*offset_ptr + c.tell(),
1985ffd83dbSDimitry Andric                                         static_cast<uint32_t>(payload_len),
1995ffd83dbSDimitry Andric                                         section_id, ConstString()});
2005ffd83dbSDimitry Andric     *offset_ptr += (c.tell() + payload_len);
2015ffd83dbSDimitry Andric   } else {
2025ffd83dbSDimitry Andric     // Invalid section id.
2035ffd83dbSDimitry Andric     return false;
2045ffd83dbSDimitry Andric   }
2055ffd83dbSDimitry Andric   return true;
2065ffd83dbSDimitry Andric }
2075ffd83dbSDimitry Andric 
DecodeSections()2085ffd83dbSDimitry Andric bool ObjectFileWasm::DecodeSections() {
2095ffd83dbSDimitry Andric   lldb::offset_t offset = kWasmHeaderSize;
2105ffd83dbSDimitry Andric   if (IsInMemory()) {
2115ffd83dbSDimitry Andric     offset += m_memory_addr;
2125ffd83dbSDimitry Andric   }
2135ffd83dbSDimitry Andric 
2145ffd83dbSDimitry Andric   while (DecodeNextSection(&offset))
2155ffd83dbSDimitry Andric     ;
2165ffd83dbSDimitry Andric   return true;
2175ffd83dbSDimitry Andric }
2185ffd83dbSDimitry Andric 
GetModuleSpecifications(const FileSpec & file,DataBufferSP & data_sp,offset_t data_offset,offset_t file_offset,offset_t length,ModuleSpecList & specs)2195ffd83dbSDimitry Andric size_t ObjectFileWasm::GetModuleSpecifications(
2205ffd83dbSDimitry Andric     const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
2215ffd83dbSDimitry Andric     offset_t file_offset, offset_t length, ModuleSpecList &specs) {
2225ffd83dbSDimitry Andric   if (!ValidateModuleHeader(data_sp)) {
2235ffd83dbSDimitry Andric     return 0;
2245ffd83dbSDimitry Andric   }
2255ffd83dbSDimitry Andric 
2265ffd83dbSDimitry Andric   ModuleSpec spec(file, ArchSpec("wasm32-unknown-unknown-wasm"));
2275ffd83dbSDimitry Andric   specs.Append(spec);
2285ffd83dbSDimitry Andric   return 1;
2295ffd83dbSDimitry Andric }
2305ffd83dbSDimitry Andric 
ObjectFileWasm(const ModuleSP & module_sp,DataBufferSP data_sp,offset_t data_offset,const FileSpec * file,offset_t offset,offset_t length)23181ad6265SDimitry Andric ObjectFileWasm::ObjectFileWasm(const ModuleSP &module_sp, DataBufferSP data_sp,
2325ffd83dbSDimitry Andric                                offset_t data_offset, const FileSpec *file,
2335ffd83dbSDimitry Andric                                offset_t offset, offset_t length)
2345ffd83dbSDimitry Andric     : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
2355ffd83dbSDimitry Andric       m_arch("wasm32-unknown-unknown-wasm") {
2365ffd83dbSDimitry Andric   m_data.SetAddressByteSize(4);
2375ffd83dbSDimitry Andric }
2385ffd83dbSDimitry Andric 
ObjectFileWasm(const lldb::ModuleSP & module_sp,lldb::WritableDataBufferSP header_data_sp,const lldb::ProcessSP & process_sp,lldb::addr_t header_addr)2395ffd83dbSDimitry Andric ObjectFileWasm::ObjectFileWasm(const lldb::ModuleSP &module_sp,
24081ad6265SDimitry Andric                                lldb::WritableDataBufferSP header_data_sp,
2415ffd83dbSDimitry Andric                                const lldb::ProcessSP &process_sp,
2425ffd83dbSDimitry Andric                                lldb::addr_t header_addr)
2435ffd83dbSDimitry Andric     : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
2445ffd83dbSDimitry Andric       m_arch("wasm32-unknown-unknown-wasm") {}
2455ffd83dbSDimitry Andric 
ParseHeader()2465ffd83dbSDimitry Andric bool ObjectFileWasm::ParseHeader() {
2475ffd83dbSDimitry Andric   // We already parsed the header during initialization.
2485ffd83dbSDimitry Andric   return true;
2495ffd83dbSDimitry Andric }
2505ffd83dbSDimitry Andric 
ParseSymtab(Symtab & symtab)2514824e7fdSDimitry Andric void ObjectFileWasm::ParseSymtab(Symtab &symtab) {}
2525ffd83dbSDimitry Andric 
GetSectionTypeFromName(llvm::StringRef Name)253e8d8bef9SDimitry Andric static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
254e8d8bef9SDimitry Andric   if (Name.consume_front(".debug_") || Name.consume_front(".zdebug_")) {
255e8d8bef9SDimitry Andric     return llvm::StringSwitch<SectionType>(Name)
256e8d8bef9SDimitry Andric         .Case("abbrev", eSectionTypeDWARFDebugAbbrev)
257e8d8bef9SDimitry Andric         .Case("abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)
258e8d8bef9SDimitry Andric         .Case("addr", eSectionTypeDWARFDebugAddr)
259e8d8bef9SDimitry Andric         .Case("aranges", eSectionTypeDWARFDebugAranges)
260e8d8bef9SDimitry Andric         .Case("cu_index", eSectionTypeDWARFDebugCuIndex)
261e8d8bef9SDimitry Andric         .Case("frame", eSectionTypeDWARFDebugFrame)
262e8d8bef9SDimitry Andric         .Case("info", eSectionTypeDWARFDebugInfo)
263e8d8bef9SDimitry Andric         .Case("info.dwo", eSectionTypeDWARFDebugInfoDwo)
264e8d8bef9SDimitry Andric         .Cases("line", "line.dwo", eSectionTypeDWARFDebugLine)
265e8d8bef9SDimitry Andric         .Cases("line_str", "line_str.dwo", eSectionTypeDWARFDebugLineStr)
266e8d8bef9SDimitry Andric         .Case("loc", eSectionTypeDWARFDebugLoc)
267e8d8bef9SDimitry Andric         .Case("loc.dwo", eSectionTypeDWARFDebugLocDwo)
268e8d8bef9SDimitry Andric         .Case("loclists", eSectionTypeDWARFDebugLocLists)
269e8d8bef9SDimitry Andric         .Case("loclists.dwo", eSectionTypeDWARFDebugLocListsDwo)
270e8d8bef9SDimitry Andric         .Case("macinfo", eSectionTypeDWARFDebugMacInfo)
271e8d8bef9SDimitry Andric         .Cases("macro", "macro.dwo", eSectionTypeDWARFDebugMacro)
272e8d8bef9SDimitry Andric         .Case("names", eSectionTypeDWARFDebugNames)
273e8d8bef9SDimitry Andric         .Case("pubnames", eSectionTypeDWARFDebugPubNames)
274e8d8bef9SDimitry Andric         .Case("pubtypes", eSectionTypeDWARFDebugPubTypes)
275e8d8bef9SDimitry Andric         .Case("ranges", eSectionTypeDWARFDebugRanges)
276e8d8bef9SDimitry Andric         .Case("rnglists", eSectionTypeDWARFDebugRngLists)
277e8d8bef9SDimitry Andric         .Case("rnglists.dwo", eSectionTypeDWARFDebugRngListsDwo)
278e8d8bef9SDimitry Andric         .Case("str", eSectionTypeDWARFDebugStr)
279e8d8bef9SDimitry Andric         .Case("str.dwo", eSectionTypeDWARFDebugStrDwo)
280e8d8bef9SDimitry Andric         .Case("str_offsets", eSectionTypeDWARFDebugStrOffsets)
281e8d8bef9SDimitry Andric         .Case("str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
282e8d8bef9SDimitry Andric         .Case("tu_index", eSectionTypeDWARFDebugTuIndex)
283e8d8bef9SDimitry Andric         .Case("types", eSectionTypeDWARFDebugTypes)
284e8d8bef9SDimitry Andric         .Case("types.dwo", eSectionTypeDWARFDebugTypesDwo)
285e8d8bef9SDimitry Andric         .Default(eSectionTypeOther);
286e8d8bef9SDimitry Andric   }
287e8d8bef9SDimitry Andric   return eSectionTypeOther;
288e8d8bef9SDimitry Andric }
289e8d8bef9SDimitry Andric 
CreateSections(SectionList & unified_section_list)2905ffd83dbSDimitry Andric void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
2915ffd83dbSDimitry Andric   if (m_sections_up)
2925ffd83dbSDimitry Andric     return;
2935ffd83dbSDimitry Andric 
2945ffd83dbSDimitry Andric   m_sections_up = std::make_unique<SectionList>();
2955ffd83dbSDimitry Andric 
2965ffd83dbSDimitry Andric   if (m_sect_infos.empty()) {
2975ffd83dbSDimitry Andric     DecodeSections();
2985ffd83dbSDimitry Andric   }
2995ffd83dbSDimitry Andric 
3005ffd83dbSDimitry Andric   for (const section_info &sect_info : m_sect_infos) {
3015ffd83dbSDimitry Andric     SectionType section_type = eSectionTypeOther;
3025ffd83dbSDimitry Andric     ConstString section_name;
3035ffd83dbSDimitry Andric     offset_t file_offset = sect_info.offset & 0xffffffff;
3045ffd83dbSDimitry Andric     addr_t vm_addr = file_offset;
3055ffd83dbSDimitry Andric     size_t vm_size = sect_info.size;
3065ffd83dbSDimitry Andric 
3075ffd83dbSDimitry Andric     if (llvm::wasm::WASM_SEC_CODE == sect_info.id) {
3085ffd83dbSDimitry Andric       section_type = eSectionTypeCode;
3095ffd83dbSDimitry Andric       section_name = ConstString("code");
3105ffd83dbSDimitry Andric 
3115ffd83dbSDimitry Andric       // A code address in DWARF for WebAssembly is the offset of an
3125ffd83dbSDimitry Andric       // instruction relative within the Code section of the WebAssembly file.
3135ffd83dbSDimitry Andric       // For this reason Section::GetFileAddress() must return zero for the
3145ffd83dbSDimitry Andric       // Code section.
3155ffd83dbSDimitry Andric       vm_addr = 0;
3165ffd83dbSDimitry Andric     } else {
317e8d8bef9SDimitry Andric       section_type = GetSectionTypeFromName(sect_info.name.GetStringRef());
3185ffd83dbSDimitry Andric       if (section_type == eSectionTypeOther)
3195ffd83dbSDimitry Andric         continue;
3205ffd83dbSDimitry Andric       section_name = sect_info.name;
3215ffd83dbSDimitry Andric       if (!IsInMemory()) {
3225ffd83dbSDimitry Andric         vm_size = 0;
3235ffd83dbSDimitry Andric         vm_addr = 0;
3245ffd83dbSDimitry Andric       }
3255ffd83dbSDimitry Andric     }
3265ffd83dbSDimitry Andric 
3275ffd83dbSDimitry Andric     SectionSP section_sp(
3285ffd83dbSDimitry Andric         new Section(GetModule(), // Module to which this section belongs.
3295ffd83dbSDimitry Andric                     this,        // ObjectFile to which this section belongs and
3305ffd83dbSDimitry Andric                                  // should read section data from.
3315ffd83dbSDimitry Andric                     section_type,   // Section ID.
3325ffd83dbSDimitry Andric                     section_name,   // Section name.
3335ffd83dbSDimitry Andric                     section_type,   // Section type.
3345ffd83dbSDimitry Andric                     vm_addr,        // VM address.
3355ffd83dbSDimitry Andric                     vm_size,        // VM size in bytes of this section.
3365ffd83dbSDimitry Andric                     file_offset,    // Offset of this section in the file.
3375ffd83dbSDimitry Andric                     sect_info.size, // Size of the section as found in the file.
3385ffd83dbSDimitry Andric                     0,              // Alignment of the section
3395ffd83dbSDimitry Andric                     0,              // Flags for this section.
3405ffd83dbSDimitry Andric                     1));            // Number of host bytes per target byte
3415ffd83dbSDimitry Andric     m_sections_up->AddSection(section_sp);
3425ffd83dbSDimitry Andric     unified_section_list.AddSection(section_sp);
3435ffd83dbSDimitry Andric   }
3445ffd83dbSDimitry Andric }
3455ffd83dbSDimitry Andric 
SetLoadAddress(Target & target,lldb::addr_t load_address,bool value_is_offset)3465ffd83dbSDimitry Andric bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address,
3475ffd83dbSDimitry Andric                                     bool value_is_offset) {
3485ffd83dbSDimitry Andric   /// In WebAssembly, linear memory is disjointed from code space. The VM can
3495ffd83dbSDimitry Andric   /// load multiple instances of a module, which logically share the same code.
3505ffd83dbSDimitry Andric   /// We represent a wasm32 code address with 64-bits, like:
3515ffd83dbSDimitry Andric   /// 63            32 31             0
3525ffd83dbSDimitry Andric   /// +---------------+---------------+
3535ffd83dbSDimitry Andric   /// +   module_id   |     offset    |
3545ffd83dbSDimitry Andric   /// +---------------+---------------+
3555ffd83dbSDimitry Andric   /// where the lower 32 bits represent a module offset (relative to the module
3565ffd83dbSDimitry Andric   /// start not to the beginning of the code section) and the higher 32 bits
3575ffd83dbSDimitry Andric   /// uniquely identify the module in the WebAssembly VM.
3585ffd83dbSDimitry Andric   /// In other words, we assume that each WebAssembly module is loaded by the
3595ffd83dbSDimitry Andric   /// engine at a 64-bit address that starts at the boundary of 4GB pages, like
3605ffd83dbSDimitry Andric   /// 0x0000000400000000 for module_id == 4.
3615ffd83dbSDimitry Andric   /// These 64-bit addresses will be used to request code ranges for a specific
3625ffd83dbSDimitry Andric   /// module from the WebAssembly engine.
3635ffd83dbSDimitry Andric 
3645ffd83dbSDimitry Andric   assert(m_memory_addr == LLDB_INVALID_ADDRESS ||
3655ffd83dbSDimitry Andric          m_memory_addr == load_address);
3665ffd83dbSDimitry Andric 
3675ffd83dbSDimitry Andric   ModuleSP module_sp = GetModule();
3685ffd83dbSDimitry Andric   if (!module_sp)
3695ffd83dbSDimitry Andric     return false;
3705ffd83dbSDimitry Andric 
3715ffd83dbSDimitry Andric   DecodeSections();
3725ffd83dbSDimitry Andric 
3735ffd83dbSDimitry Andric   size_t num_loaded_sections = 0;
3745ffd83dbSDimitry Andric   SectionList *section_list = GetSectionList();
3755ffd83dbSDimitry Andric   if (!section_list)
3765ffd83dbSDimitry Andric     return false;
3775ffd83dbSDimitry Andric 
3785ffd83dbSDimitry Andric   const size_t num_sections = section_list->GetSize();
3795ffd83dbSDimitry Andric   for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
3805ffd83dbSDimitry Andric     SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
3815ffd83dbSDimitry Andric     if (target.SetSectionLoadAddress(
3825ffd83dbSDimitry Andric             section_sp, load_address | section_sp->GetFileOffset())) {
3835ffd83dbSDimitry Andric       ++num_loaded_sections;
3845ffd83dbSDimitry Andric     }
3855ffd83dbSDimitry Andric   }
3865ffd83dbSDimitry Andric 
3875ffd83dbSDimitry Andric   return num_loaded_sections > 0;
3885ffd83dbSDimitry Andric }
3895ffd83dbSDimitry Andric 
ReadImageData(offset_t offset,uint32_t size)3905ffd83dbSDimitry Andric DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) {
3915ffd83dbSDimitry Andric   DataExtractor data;
3925ffd83dbSDimitry Andric   if (m_file) {
3935ffd83dbSDimitry Andric     if (offset < GetByteSize()) {
3945ffd83dbSDimitry Andric       size = std::min(static_cast<uint64_t>(size), GetByteSize() - offset);
3955ffd83dbSDimitry Andric       auto buffer_sp = MapFileData(m_file, size, offset);
3965ffd83dbSDimitry Andric       return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize());
3975ffd83dbSDimitry Andric     }
3985ffd83dbSDimitry Andric   } else {
3995ffd83dbSDimitry Andric     ProcessSP process_sp(m_process_wp.lock());
4005ffd83dbSDimitry Andric     if (process_sp) {
4015ffd83dbSDimitry Andric       auto data_up = std::make_unique<DataBufferHeap>(size, 0);
4025ffd83dbSDimitry Andric       Status readmem_error;
4035ffd83dbSDimitry Andric       size_t bytes_read = process_sp->ReadMemory(
4045ffd83dbSDimitry Andric           offset, data_up->GetBytes(), data_up->GetByteSize(), readmem_error);
4055ffd83dbSDimitry Andric       if (bytes_read > 0) {
4065ffd83dbSDimitry Andric         DataBufferSP buffer_sp(data_up.release());
4075ffd83dbSDimitry Andric         data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
4085ffd83dbSDimitry Andric       }
4095ffd83dbSDimitry Andric     }
4105ffd83dbSDimitry Andric   }
4115ffd83dbSDimitry Andric 
4125ffd83dbSDimitry Andric   data.SetByteOrder(GetByteOrder());
4135ffd83dbSDimitry Andric   return data;
4145ffd83dbSDimitry Andric }
4155ffd83dbSDimitry Andric 
GetExternalDebugInfoFileSpec()416*bdd1243dSDimitry Andric std::optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() {
4175ffd83dbSDimitry Andric   static ConstString g_sect_name_external_debug_info("external_debug_info");
4185ffd83dbSDimitry Andric 
4195ffd83dbSDimitry Andric   for (const section_info &sect_info : m_sect_infos) {
4205ffd83dbSDimitry Andric     if (g_sect_name_external_debug_info == sect_info.name) {
4215ffd83dbSDimitry Andric       const uint32_t kBufferSize = 1024;
4225ffd83dbSDimitry Andric       DataExtractor section_header_data =
4235ffd83dbSDimitry Andric           ReadImageData(sect_info.offset, kBufferSize);
4245ffd83dbSDimitry Andric       llvm::DataExtractor data = section_header_data.GetAsLLVM();
4255ffd83dbSDimitry Andric       llvm::DataExtractor::Cursor c(0);
426*bdd1243dSDimitry Andric       std::optional<ConstString> symbols_url = GetWasmString(data, c);
4275ffd83dbSDimitry Andric       if (symbols_url)
4285ffd83dbSDimitry Andric         return FileSpec(symbols_url->GetStringRef());
4295ffd83dbSDimitry Andric     }
4305ffd83dbSDimitry Andric   }
431*bdd1243dSDimitry Andric   return std::nullopt;
4325ffd83dbSDimitry Andric }
4335ffd83dbSDimitry Andric 
Dump(Stream * s)4345ffd83dbSDimitry Andric void ObjectFileWasm::Dump(Stream *s) {
4355ffd83dbSDimitry Andric   ModuleSP module_sp(GetModule());
4365ffd83dbSDimitry Andric   if (!module_sp)
4375ffd83dbSDimitry Andric     return;
4385ffd83dbSDimitry Andric 
4395ffd83dbSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
4405ffd83dbSDimitry Andric 
4415ffd83dbSDimitry Andric   llvm::raw_ostream &ostream = s->AsRawOstream();
4425ffd83dbSDimitry Andric   ostream << static_cast<void *>(this) << ": ";
4435ffd83dbSDimitry Andric   s->Indent();
4445ffd83dbSDimitry Andric   ostream << "ObjectFileWasm, file = '";
4455ffd83dbSDimitry Andric   m_file.Dump(ostream);
4465ffd83dbSDimitry Andric   ostream << "', arch = ";
4475ffd83dbSDimitry Andric   ostream << GetArchitecture().GetArchitectureName() << "\n";
4485ffd83dbSDimitry Andric 
4495ffd83dbSDimitry Andric   SectionList *sections = GetSectionList();
4505ffd83dbSDimitry Andric   if (sections) {
4515ffd83dbSDimitry Andric     sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
4525ffd83dbSDimitry Andric                    UINT32_MAX);
4535ffd83dbSDimitry Andric   }
4545ffd83dbSDimitry Andric   ostream << "\n";
4555ffd83dbSDimitry Andric   DumpSectionHeaders(ostream);
4565ffd83dbSDimitry Andric   ostream << "\n";
4575ffd83dbSDimitry Andric }
4585ffd83dbSDimitry Andric 
DumpSectionHeader(llvm::raw_ostream & ostream,const section_info_t & sh)4595ffd83dbSDimitry Andric void ObjectFileWasm::DumpSectionHeader(llvm::raw_ostream &ostream,
4605ffd83dbSDimitry Andric                                        const section_info_t &sh) {
4615ffd83dbSDimitry Andric   ostream << llvm::left_justify(sh.name.GetStringRef(), 16) << " "
4625ffd83dbSDimitry Andric           << llvm::format_hex(sh.offset, 10) << " "
4635ffd83dbSDimitry Andric           << llvm::format_hex(sh.size, 10) << " " << llvm::format_hex(sh.id, 6)
4645ffd83dbSDimitry Andric           << "\n";
4655ffd83dbSDimitry Andric }
4665ffd83dbSDimitry Andric 
DumpSectionHeaders(llvm::raw_ostream & ostream)4675ffd83dbSDimitry Andric void ObjectFileWasm::DumpSectionHeaders(llvm::raw_ostream &ostream) {
4685ffd83dbSDimitry Andric   ostream << "Section Headers\n";
4695ffd83dbSDimitry Andric   ostream << "IDX  name             addr       size       id\n";
4705ffd83dbSDimitry Andric   ostream << "==== ---------------- ---------- ---------- ------\n";
4715ffd83dbSDimitry Andric 
4725ffd83dbSDimitry Andric   uint32_t idx = 0;
4735ffd83dbSDimitry Andric   for (auto pos = m_sect_infos.begin(); pos != m_sect_infos.end();
4745ffd83dbSDimitry Andric        ++pos, ++idx) {
4755ffd83dbSDimitry Andric     ostream << "[" << llvm::format_decimal(idx, 2) << "] ";
4765ffd83dbSDimitry Andric     ObjectFileWasm::DumpSectionHeader(ostream, *pos);
4775ffd83dbSDimitry Andric   }
4785ffd83dbSDimitry Andric }
479