1*4bafceceSPaolo Severini //===-- ObjectFileWasm.cpp ------------------------------------------------===// 2*4bafceceSPaolo Severini // 3*4bafceceSPaolo Severini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4bafceceSPaolo Severini // See https://llvm.org/LICENSE.txt for license information. 5*4bafceceSPaolo Severini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4bafceceSPaolo Severini // 7*4bafceceSPaolo Severini //===----------------------------------------------------------------------===// 8*4bafceceSPaolo Severini 9*4bafceceSPaolo Severini #include "ObjectFileWasm.h" 10*4bafceceSPaolo Severini #include "lldb/Core/Module.h" 11*4bafceceSPaolo Severini #include "lldb/Core/ModuleSpec.h" 12*4bafceceSPaolo Severini #include "lldb/Core/PluginManager.h" 13*4bafceceSPaolo Severini #include "lldb/Core/Section.h" 14*4bafceceSPaolo Severini #include "lldb/Target/Process.h" 15*4bafceceSPaolo Severini #include "lldb/Target/SectionLoadList.h" 16*4bafceceSPaolo Severini #include "lldb/Target/Target.h" 17*4bafceceSPaolo Severini #include "lldb/Utility/DataBufferHeap.h" 18*4bafceceSPaolo Severini #include "lldb/Utility/Log.h" 19*4bafceceSPaolo Severini #include "llvm/ADT/ArrayRef.h" 20*4bafceceSPaolo Severini #include "llvm/ADT/SmallVector.h" 21*4bafceceSPaolo Severini #include "llvm/ADT/StringRef.h" 22*4bafceceSPaolo Severini #include "llvm/BinaryFormat/Magic.h" 23*4bafceceSPaolo Severini #include "llvm/BinaryFormat/Wasm.h" 24*4bafceceSPaolo Severini #include "llvm/Support/Endian.h" 25*4bafceceSPaolo Severini #include "llvm/Support/Format.h" 26*4bafceceSPaolo Severini 27*4bafceceSPaolo Severini using namespace lldb; 28*4bafceceSPaolo Severini using namespace lldb_private; 29*4bafceceSPaolo Severini using namespace lldb_private::wasm; 30*4bafceceSPaolo Severini 31*4bafceceSPaolo Severini static const uint32_t kWasmHeaderSize = 32*4bafceceSPaolo Severini sizeof(llvm::wasm::WasmMagic) + sizeof(llvm::wasm::WasmVersion); 33*4bafceceSPaolo Severini 34*4bafceceSPaolo Severini /// Checks whether the data buffer starts with a valid Wasm module header. 35*4bafceceSPaolo Severini static bool ValidateModuleHeader(const DataBufferSP &data_sp) { 36*4bafceceSPaolo Severini if (!data_sp || data_sp->GetByteSize() < kWasmHeaderSize) 37*4bafceceSPaolo Severini return false; 38*4bafceceSPaolo Severini 39*4bafceceSPaolo Severini if (llvm::identify_magic(toStringRef(data_sp->GetData())) != 40*4bafceceSPaolo Severini llvm::file_magic::wasm_object) 41*4bafceceSPaolo Severini return false; 42*4bafceceSPaolo Severini 43*4bafceceSPaolo Severini uint8_t *Ptr = data_sp->GetBytes() + sizeof(llvm::wasm::WasmMagic); 44*4bafceceSPaolo Severini 45*4bafceceSPaolo Severini uint32_t version = llvm::support::endian::read32le(Ptr); 46*4bafceceSPaolo Severini return version == llvm::wasm::WasmVersion; 47*4bafceceSPaolo Severini } 48*4bafceceSPaolo Severini 49*4bafceceSPaolo Severini static llvm::Optional<ConstString> 50*4bafceceSPaolo Severini GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) { 51*4bafceceSPaolo Severini // A Wasm string is encoded as a vector of UTF-8 codes. 52*4bafceceSPaolo Severini // Vectors are encoded with their u32 length followed by the element 53*4bafceceSPaolo Severini // sequence. 54*4bafceceSPaolo Severini uint64_t len = data.getULEB128(c); 55*4bafceceSPaolo Severini if (!c) { 56*4bafceceSPaolo Severini consumeError(c.takeError()); 57*4bafceceSPaolo Severini return llvm::None; 58*4bafceceSPaolo Severini } 59*4bafceceSPaolo Severini 60*4bafceceSPaolo Severini if (len >= (uint64_t(1) << 32)) { 61*4bafceceSPaolo Severini return llvm::None; 62*4bafceceSPaolo Severini } 63*4bafceceSPaolo Severini 64*4bafceceSPaolo Severini llvm::SmallVector<uint8_t, 32> str_storage; 65*4bafceceSPaolo Severini data.getU8(c, str_storage, len); 66*4bafceceSPaolo Severini if (!c) { 67*4bafceceSPaolo Severini consumeError(c.takeError()); 68*4bafceceSPaolo Severini return llvm::None; 69*4bafceceSPaolo Severini } 70*4bafceceSPaolo Severini 71*4bafceceSPaolo Severini llvm::StringRef str = toStringRef(makeArrayRef(str_storage)); 72*4bafceceSPaolo Severini return ConstString(str); 73*4bafceceSPaolo Severini } 74*4bafceceSPaolo Severini 75*4bafceceSPaolo Severini void ObjectFileWasm::Initialize() { 76*4bafceceSPaolo Severini PluginManager::RegisterPlugin(GetPluginNameStatic(), 77*4bafceceSPaolo Severini GetPluginDescriptionStatic(), CreateInstance, 78*4bafceceSPaolo Severini CreateMemoryInstance, GetModuleSpecifications); 79*4bafceceSPaolo Severini } 80*4bafceceSPaolo Severini 81*4bafceceSPaolo Severini void ObjectFileWasm::Terminate() { 82*4bafceceSPaolo Severini PluginManager::UnregisterPlugin(CreateInstance); 83*4bafceceSPaolo Severini } 84*4bafceceSPaolo Severini 85*4bafceceSPaolo Severini ConstString ObjectFileWasm::GetPluginNameStatic() { 86*4bafceceSPaolo Severini static ConstString g_name("wasm"); 87*4bafceceSPaolo Severini return g_name; 88*4bafceceSPaolo Severini } 89*4bafceceSPaolo Severini 90*4bafceceSPaolo Severini ObjectFile * 91*4bafceceSPaolo Severini ObjectFileWasm::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp, 92*4bafceceSPaolo Severini offset_t data_offset, const FileSpec *file, 93*4bafceceSPaolo Severini offset_t file_offset, offset_t length) { 94*4bafceceSPaolo Severini Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 95*4bafceceSPaolo Severini 96*4bafceceSPaolo Severini if (!data_sp) { 97*4bafceceSPaolo Severini data_sp = MapFileData(*file, length, file_offset); 98*4bafceceSPaolo Severini if (!data_sp) { 99*4bafceceSPaolo Severini LLDB_LOGF(log, "Failed to create ObjectFileWasm instance for file %s", 100*4bafceceSPaolo Severini file->GetPath().c_str()); 101*4bafceceSPaolo Severini return nullptr; 102*4bafceceSPaolo Severini } 103*4bafceceSPaolo Severini data_offset = 0; 104*4bafceceSPaolo Severini } 105*4bafceceSPaolo Severini 106*4bafceceSPaolo Severini assert(data_sp); 107*4bafceceSPaolo Severini if (!ValidateModuleHeader(data_sp)) { 108*4bafceceSPaolo Severini LLDB_LOGF(log, 109*4bafceceSPaolo Severini "Failed to create ObjectFileWasm instance: invalid Wasm header"); 110*4bafceceSPaolo Severini return nullptr; 111*4bafceceSPaolo Severini } 112*4bafceceSPaolo Severini 113*4bafceceSPaolo Severini // Update the data to contain the entire file if it doesn't contain it 114*4bafceceSPaolo Severini // already. 115*4bafceceSPaolo Severini if (data_sp->GetByteSize() < length) { 116*4bafceceSPaolo Severini data_sp = MapFileData(*file, length, file_offset); 117*4bafceceSPaolo Severini if (!data_sp) { 118*4bafceceSPaolo Severini LLDB_LOGF(log, 119*4bafceceSPaolo Severini "Failed to create ObjectFileWasm instance: cannot read file %s", 120*4bafceceSPaolo Severini file->GetPath().c_str()); 121*4bafceceSPaolo Severini return nullptr; 122*4bafceceSPaolo Severini } 123*4bafceceSPaolo Severini data_offset = 0; 124*4bafceceSPaolo Severini } 125*4bafceceSPaolo Severini 126*4bafceceSPaolo Severini std::unique_ptr<ObjectFileWasm> objfile_up(new ObjectFileWasm( 127*4bafceceSPaolo Severini module_sp, data_sp, data_offset, file, file_offset, length)); 128*4bafceceSPaolo Severini ArchSpec spec = objfile_up->GetArchitecture(); 129*4bafceceSPaolo Severini if (spec && objfile_up->SetModulesArchitecture(spec)) { 130*4bafceceSPaolo Severini LLDB_LOGF(log, 131*4bafceceSPaolo Severini "%p ObjectFileWasm::CreateInstance() module = %p (%s), file = %s", 132*4bafceceSPaolo Severini static_cast<void *>(objfile_up.get()), 133*4bafceceSPaolo Severini static_cast<void *>(objfile_up->GetModule().get()), 134*4bafceceSPaolo Severini objfile_up->GetModule()->GetSpecificationDescription().c_str(), 135*4bafceceSPaolo Severini file ? file->GetPath().c_str() : "<NULL>"); 136*4bafceceSPaolo Severini return objfile_up.release(); 137*4bafceceSPaolo Severini } 138*4bafceceSPaolo Severini 139*4bafceceSPaolo Severini LLDB_LOGF(log, "Failed to create ObjectFileWasm instance"); 140*4bafceceSPaolo Severini return nullptr; 141*4bafceceSPaolo Severini } 142*4bafceceSPaolo Severini 143*4bafceceSPaolo Severini ObjectFile *ObjectFileWasm::CreateMemoryInstance(const ModuleSP &module_sp, 144*4bafceceSPaolo Severini DataBufferSP &data_sp, 145*4bafceceSPaolo Severini const ProcessSP &process_sp, 146*4bafceceSPaolo Severini addr_t header_addr) { 147*4bafceceSPaolo Severini if (!ValidateModuleHeader(data_sp)) 148*4bafceceSPaolo Severini return nullptr; 149*4bafceceSPaolo Severini 150*4bafceceSPaolo Severini std::unique_ptr<ObjectFileWasm> objfile_up( 151*4bafceceSPaolo Severini new ObjectFileWasm(module_sp, data_sp, process_sp, header_addr)); 152*4bafceceSPaolo Severini ArchSpec spec = objfile_up->GetArchitecture(); 153*4bafceceSPaolo Severini if (spec && objfile_up->SetModulesArchitecture(spec)) 154*4bafceceSPaolo Severini return objfile_up.release(); 155*4bafceceSPaolo Severini return nullptr; 156*4bafceceSPaolo Severini } 157*4bafceceSPaolo Severini 158*4bafceceSPaolo Severini bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) { 159*4bafceceSPaolo Severini // Buffer sufficient to read a section header and find the pointer to the next 160*4bafceceSPaolo Severini // section. 161*4bafceceSPaolo Severini const uint32_t kBufferSize = 1024; 162*4bafceceSPaolo Severini DataExtractor section_header_data = ReadImageData(*offset_ptr, kBufferSize); 163*4bafceceSPaolo Severini 164*4bafceceSPaolo Severini llvm::DataExtractor data = section_header_data.GetAsLLVM(); 165*4bafceceSPaolo Severini llvm::DataExtractor::Cursor c(0); 166*4bafceceSPaolo Severini 167*4bafceceSPaolo Severini // Each section consists of: 168*4bafceceSPaolo Severini // - a one-byte section id, 169*4bafceceSPaolo Severini // - the u32 size of the contents, in bytes, 170*4bafceceSPaolo Severini // - the actual contents. 171*4bafceceSPaolo Severini uint8_t section_id = data.getU8(c); 172*4bafceceSPaolo Severini uint64_t payload_len = data.getULEB128(c); 173*4bafceceSPaolo Severini if (!c) 174*4bafceceSPaolo Severini return !llvm::errorToBool(c.takeError()); 175*4bafceceSPaolo Severini 176*4bafceceSPaolo Severini if (payload_len >= (uint64_t(1) << 32)) 177*4bafceceSPaolo Severini return false; 178*4bafceceSPaolo Severini 179*4bafceceSPaolo Severini if (section_id == llvm::wasm::WASM_SEC_CUSTOM) { 180*4bafceceSPaolo Severini lldb::offset_t prev_offset = c.tell(); 181*4bafceceSPaolo Severini llvm::Optional<ConstString> sect_name = GetWasmString(data, c); 182*4bafceceSPaolo Severini if (!sect_name) 183*4bafceceSPaolo Severini return false; 184*4bafceceSPaolo Severini 185*4bafceceSPaolo Severini if (payload_len < c.tell() - prev_offset) 186*4bafceceSPaolo Severini return false; 187*4bafceceSPaolo Severini 188*4bafceceSPaolo Severini uint32_t section_length = payload_len - (c.tell() - prev_offset); 189*4bafceceSPaolo Severini m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), section_length, 190*4bafceceSPaolo Severini section_id, *sect_name}); 191*4bafceceSPaolo Severini *offset_ptr += (c.tell() + section_length); 192*4bafceceSPaolo Severini } else if (section_id <= llvm::wasm::WASM_SEC_EVENT) { 193*4bafceceSPaolo Severini m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), 194*4bafceceSPaolo Severini static_cast<uint32_t>(payload_len), 195*4bafceceSPaolo Severini section_id, ConstString()}); 196*4bafceceSPaolo Severini *offset_ptr += (c.tell() + payload_len); 197*4bafceceSPaolo Severini } else { 198*4bafceceSPaolo Severini // Invalid section id. 199*4bafceceSPaolo Severini return false; 200*4bafceceSPaolo Severini } 201*4bafceceSPaolo Severini return true; 202*4bafceceSPaolo Severini } 203*4bafceceSPaolo Severini 204*4bafceceSPaolo Severini bool ObjectFileWasm::DecodeSections() { 205*4bafceceSPaolo Severini lldb::offset_t offset = kWasmHeaderSize; 206*4bafceceSPaolo Severini if (IsInMemory()) { 207*4bafceceSPaolo Severini offset += m_memory_addr; 208*4bafceceSPaolo Severini } 209*4bafceceSPaolo Severini 210*4bafceceSPaolo Severini while (DecodeNextSection(&offset)) 211*4bafceceSPaolo Severini ; 212*4bafceceSPaolo Severini return true; 213*4bafceceSPaolo Severini } 214*4bafceceSPaolo Severini 215*4bafceceSPaolo Severini size_t ObjectFileWasm::GetModuleSpecifications( 216*4bafceceSPaolo Severini const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, 217*4bafceceSPaolo Severini offset_t file_offset, offset_t length, ModuleSpecList &specs) { 218*4bafceceSPaolo Severini if (!ValidateModuleHeader(data_sp)) { 219*4bafceceSPaolo Severini return 0; 220*4bafceceSPaolo Severini } 221*4bafceceSPaolo Severini 222*4bafceceSPaolo Severini ModuleSpec spec(file, ArchSpec("wasm32-unknown-unknown-wasm")); 223*4bafceceSPaolo Severini specs.Append(spec); 224*4bafceceSPaolo Severini return 1; 225*4bafceceSPaolo Severini } 226*4bafceceSPaolo Severini 227*4bafceceSPaolo Severini ObjectFileWasm::ObjectFileWasm(const ModuleSP &module_sp, DataBufferSP &data_sp, 228*4bafceceSPaolo Severini offset_t data_offset, const FileSpec *file, 229*4bafceceSPaolo Severini offset_t offset, offset_t length) 230*4bafceceSPaolo Severini : ObjectFile(module_sp, file, offset, length, data_sp, data_offset), 231*4bafceceSPaolo Severini m_arch("wasm32-unknown-unknown-wasm"), m_code_section_offset(0) { 232*4bafceceSPaolo Severini m_data.SetAddressByteSize(4); 233*4bafceceSPaolo Severini } 234*4bafceceSPaolo Severini 235*4bafceceSPaolo Severini ObjectFileWasm::ObjectFileWasm(const lldb::ModuleSP &module_sp, 236*4bafceceSPaolo Severini lldb::DataBufferSP &header_data_sp, 237*4bafceceSPaolo Severini const lldb::ProcessSP &process_sp, 238*4bafceceSPaolo Severini lldb::addr_t header_addr) 239*4bafceceSPaolo Severini : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), 240*4bafceceSPaolo Severini m_arch("wasm32-unknown-unknown-wasm"), m_code_section_offset(0) {} 241*4bafceceSPaolo Severini 242*4bafceceSPaolo Severini bool ObjectFileWasm::ParseHeader() { 243*4bafceceSPaolo Severini // We already parsed the header during initialization. 244*4bafceceSPaolo Severini return true; 245*4bafceceSPaolo Severini } 246*4bafceceSPaolo Severini 247*4bafceceSPaolo Severini Symtab *ObjectFileWasm::GetSymtab() { return nullptr; } 248*4bafceceSPaolo Severini 249*4bafceceSPaolo Severini void ObjectFileWasm::CreateSections(SectionList &unified_section_list) { 250*4bafceceSPaolo Severini if (m_sections_up) 251*4bafceceSPaolo Severini return; 252*4bafceceSPaolo Severini 253*4bafceceSPaolo Severini m_sections_up = std::make_unique<SectionList>(); 254*4bafceceSPaolo Severini 255*4bafceceSPaolo Severini if (m_sect_infos.empty()) { 256*4bafceceSPaolo Severini DecodeSections(); 257*4bafceceSPaolo Severini } 258*4bafceceSPaolo Severini 259*4bafceceSPaolo Severini for (const section_info §_info : m_sect_infos) { 260*4bafceceSPaolo Severini SectionType section_type = eSectionTypeOther; 261*4bafceceSPaolo Severini ConstString section_name; 262*4bafceceSPaolo Severini offset_t file_offset = 0; 263*4bafceceSPaolo Severini addr_t vm_addr = 0; 264*4bafceceSPaolo Severini size_t vm_size = 0; 265*4bafceceSPaolo Severini 266*4bafceceSPaolo Severini if (llvm::wasm::WASM_SEC_CODE == sect_info.id) { 267*4bafceceSPaolo Severini section_type = eSectionTypeCode; 268*4bafceceSPaolo Severini section_name = ConstString("code"); 269*4bafceceSPaolo Severini m_code_section_offset = sect_info.offset & 0xffffffff; 270*4bafceceSPaolo Severini vm_size = sect_info.size; 271*4bafceceSPaolo Severini } else { 272*4bafceceSPaolo Severini section_type = 273*4bafceceSPaolo Severini llvm::StringSwitch<SectionType>(sect_info.name.GetStringRef()) 274*4bafceceSPaolo Severini .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev) 275*4bafceceSPaolo Severini .Case(".debug_addr", eSectionTypeDWARFDebugAddr) 276*4bafceceSPaolo Severini .Case(".debug_aranges", eSectionTypeDWARFDebugAranges) 277*4bafceceSPaolo Severini .Case(".debug_cu_index", eSectionTypeDWARFDebugCuIndex) 278*4bafceceSPaolo Severini .Case(".debug_frame", eSectionTypeDWARFDebugFrame) 279*4bafceceSPaolo Severini .Case(".debug_info", eSectionTypeDWARFDebugInfo) 280*4bafceceSPaolo Severini .Case(".debug_line", eSectionTypeDWARFDebugLine) 281*4bafceceSPaolo Severini .Case(".debug_line_str", eSectionTypeDWARFDebugLineStr) 282*4bafceceSPaolo Severini .Case(".debug_loc", eSectionTypeDWARFDebugLoc) 283*4bafceceSPaolo Severini .Case(".debug_loclists", eSectionTypeDWARFDebugLocLists) 284*4bafceceSPaolo Severini .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo) 285*4bafceceSPaolo Severini .Case(".debug_macro", eSectionTypeDWARFDebugMacro) 286*4bafceceSPaolo Severini .Case(".debug_names", eSectionTypeDWARFDebugNames) 287*4bafceceSPaolo Severini .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames) 288*4bafceceSPaolo Severini .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes) 289*4bafceceSPaolo Severini .Case(".debug_ranges", eSectionTypeDWARFDebugRanges) 290*4bafceceSPaolo Severini .Case(".debug_rnglists", eSectionTypeDWARFDebugRngLists) 291*4bafceceSPaolo Severini .Case(".debug_str", eSectionTypeDWARFDebugStr) 292*4bafceceSPaolo Severini .Case(".debug_str_offsets", eSectionTypeDWARFDebugStrOffsets) 293*4bafceceSPaolo Severini .Case(".debug_types", eSectionTypeDWARFDebugTypes) 294*4bafceceSPaolo Severini .Default(eSectionTypeOther); 295*4bafceceSPaolo Severini if (section_type == eSectionTypeOther) 296*4bafceceSPaolo Severini continue; 297*4bafceceSPaolo Severini section_name = sect_info.name; 298*4bafceceSPaolo Severini file_offset = sect_info.offset & 0xffffffff; 299*4bafceceSPaolo Severini if (IsInMemory()) { 300*4bafceceSPaolo Severini vm_addr = sect_info.offset & 0xffffffff; 301*4bafceceSPaolo Severini vm_size = sect_info.size; 302*4bafceceSPaolo Severini } 303*4bafceceSPaolo Severini } 304*4bafceceSPaolo Severini 305*4bafceceSPaolo Severini SectionSP section_sp( 306*4bafceceSPaolo Severini new Section(GetModule(), // Module to which this section belongs. 307*4bafceceSPaolo Severini this, // ObjectFile to which this section belongs and 308*4bafceceSPaolo Severini // should read section data from. 309*4bafceceSPaolo Severini section_type, // Section ID. 310*4bafceceSPaolo Severini section_name, // Section name. 311*4bafceceSPaolo Severini section_type, // Section type. 312*4bafceceSPaolo Severini vm_addr, // VM address. 313*4bafceceSPaolo Severini vm_size, // VM size in bytes of this section. 314*4bafceceSPaolo Severini file_offset, // Offset of this section in the file. 315*4bafceceSPaolo Severini sect_info.size, // Size of the section as found in the file. 316*4bafceceSPaolo Severini 0, // Alignment of the section 317*4bafceceSPaolo Severini 0, // Flags for this section. 318*4bafceceSPaolo Severini 1)); // Number of host bytes per target byte 319*4bafceceSPaolo Severini m_sections_up->AddSection(section_sp); 320*4bafceceSPaolo Severini unified_section_list.AddSection(section_sp); 321*4bafceceSPaolo Severini } 322*4bafceceSPaolo Severini } 323*4bafceceSPaolo Severini 324*4bafceceSPaolo Severini bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address, 325*4bafceceSPaolo Severini bool value_is_offset) { 326*4bafceceSPaolo Severini /// In WebAssembly, linear memory is disjointed from code space. The VM can 327*4bafceceSPaolo Severini /// load multiple instances of a module, which logically share the same code. 328*4bafceceSPaolo Severini /// We represent a wasm32 code address with 64-bits, like: 329*4bafceceSPaolo Severini /// 63 32 31 0 330*4bafceceSPaolo Severini /// +---------------+---------------+ 331*4bafceceSPaolo Severini /// + module_id | offset | 332*4bafceceSPaolo Severini /// +---------------+---------------+ 333*4bafceceSPaolo Severini /// where the lower 32 bits represent a module offset (relative to the module 334*4bafceceSPaolo Severini /// start not to the beginning of the code section) and the higher 32 bits 335*4bafceceSPaolo Severini /// uniquely identify the module in the WebAssembly VM. 336*4bafceceSPaolo Severini /// In other words, we assume that each WebAssembly module is loaded by the 337*4bafceceSPaolo Severini /// engine at a 64-bit address that starts at the boundary of 4GB pages, like 338*4bafceceSPaolo Severini /// 0x0000000400000000 for module_id == 4. 339*4bafceceSPaolo Severini /// These 64-bit addresses will be used to request code ranges for a specific 340*4bafceceSPaolo Severini /// module from the WebAssembly engine. 341*4bafceceSPaolo Severini ModuleSP module_sp = GetModule(); 342*4bafceceSPaolo Severini if (!module_sp) 343*4bafceceSPaolo Severini return false; 344*4bafceceSPaolo Severini 345*4bafceceSPaolo Severini DecodeSections(); 346*4bafceceSPaolo Severini 347*4bafceceSPaolo Severini size_t num_loaded_sections = 0; 348*4bafceceSPaolo Severini SectionList *section_list = GetSectionList(); 349*4bafceceSPaolo Severini if (!section_list) 350*4bafceceSPaolo Severini return false; 351*4bafceceSPaolo Severini 352*4bafceceSPaolo Severini const size_t num_sections = section_list->GetSize(); 353*4bafceceSPaolo Severini size_t sect_idx = 0; 354*4bafceceSPaolo Severini 355*4bafceceSPaolo Severini for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { 356*4bafceceSPaolo Severini SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); 357*4bafceceSPaolo Severini if (target.GetSectionLoadList().SetSectionLoadAddress( 358*4bafceceSPaolo Severini section_sp, load_address | section_sp->GetFileAddress())) { 359*4bafceceSPaolo Severini ++num_loaded_sections; 360*4bafceceSPaolo Severini } 361*4bafceceSPaolo Severini } 362*4bafceceSPaolo Severini 363*4bafceceSPaolo Severini return num_loaded_sections > 0; 364*4bafceceSPaolo Severini } 365*4bafceceSPaolo Severini 366*4bafceceSPaolo Severini DataExtractor ObjectFileWasm::ReadImageData(uint64_t offset, size_t size) { 367*4bafceceSPaolo Severini DataExtractor data; 368*4bafceceSPaolo Severini if (m_file) { 369*4bafceceSPaolo Severini if (offset < GetByteSize()) { 370*4bafceceSPaolo Severini size = std::min(size, GetByteSize() - offset); 371*4bafceceSPaolo Severini auto buffer_sp = MapFileData(m_file, size, offset); 372*4bafceceSPaolo Severini return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); 373*4bafceceSPaolo Severini } 374*4bafceceSPaolo Severini } else { 375*4bafceceSPaolo Severini ProcessSP process_sp(m_process_wp.lock()); 376*4bafceceSPaolo Severini if (process_sp) { 377*4bafceceSPaolo Severini auto data_up = std::make_unique<DataBufferHeap>(size, 0); 378*4bafceceSPaolo Severini Status readmem_error; 379*4bafceceSPaolo Severini size_t bytes_read = process_sp->ReadMemory( 380*4bafceceSPaolo Severini offset, data_up->GetBytes(), data_up->GetByteSize(), readmem_error); 381*4bafceceSPaolo Severini if (bytes_read > 0) { 382*4bafceceSPaolo Severini DataBufferSP buffer_sp(data_up.release()); 383*4bafceceSPaolo Severini data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); 384*4bafceceSPaolo Severini } 385*4bafceceSPaolo Severini } 386*4bafceceSPaolo Severini } 387*4bafceceSPaolo Severini 388*4bafceceSPaolo Severini data.SetByteOrder(GetByteOrder()); 389*4bafceceSPaolo Severini return data; 390*4bafceceSPaolo Severini } 391*4bafceceSPaolo Severini 392*4bafceceSPaolo Severini void ObjectFileWasm::Dump(Stream *s) { 393*4bafceceSPaolo Severini ModuleSP module_sp(GetModule()); 394*4bafceceSPaolo Severini if (!module_sp) 395*4bafceceSPaolo Severini return; 396*4bafceceSPaolo Severini 397*4bafceceSPaolo Severini std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); 398*4bafceceSPaolo Severini 399*4bafceceSPaolo Severini llvm::raw_ostream &ostream = s->AsRawOstream(); 400*4bafceceSPaolo Severini ostream << static_cast<void *>(this) << ": "; 401*4bafceceSPaolo Severini s->Indent(); 402*4bafceceSPaolo Severini ostream << "ObjectFileWasm, file = '"; 403*4bafceceSPaolo Severini m_file.Dump(ostream); 404*4bafceceSPaolo Severini ostream << "', arch = "; 405*4bafceceSPaolo Severini ostream << GetArchitecture().GetArchitectureName() << "\n"; 406*4bafceceSPaolo Severini 407*4bafceceSPaolo Severini SectionList *sections = GetSectionList(); 408*4bafceceSPaolo Severini if (sections) { 409*4bafceceSPaolo Severini sections->Dump(s, nullptr, true, UINT32_MAX); 410*4bafceceSPaolo Severini } 411*4bafceceSPaolo Severini ostream << "\n"; 412*4bafceceSPaolo Severini DumpSectionHeaders(ostream); 413*4bafceceSPaolo Severini ostream << "\n"; 414*4bafceceSPaolo Severini } 415*4bafceceSPaolo Severini 416*4bafceceSPaolo Severini void ObjectFileWasm::DumpSectionHeader(llvm::raw_ostream &ostream, 417*4bafceceSPaolo Severini const section_info_t &sh) { 418*4bafceceSPaolo Severini ostream << llvm::left_justify(sh.name.GetStringRef(), 16) << " " 419*4bafceceSPaolo Severini << llvm::format_hex(sh.offset, 10) << " " 420*4bafceceSPaolo Severini << llvm::format_hex(sh.size, 10) << " " << llvm::format_hex(sh.id, 6) 421*4bafceceSPaolo Severini << "\n"; 422*4bafceceSPaolo Severini } 423*4bafceceSPaolo Severini 424*4bafceceSPaolo Severini void ObjectFileWasm::DumpSectionHeaders(llvm::raw_ostream &ostream) { 425*4bafceceSPaolo Severini ostream << "Section Headers\n"; 426*4bafceceSPaolo Severini ostream << "IDX name addr size id\n"; 427*4bafceceSPaolo Severini ostream << "==== ---------------- ---------- ---------- ------\n"; 428*4bafceceSPaolo Severini 429*4bafceceSPaolo Severini uint32_t idx = 0; 430*4bafceceSPaolo Severini for (auto pos = m_sect_infos.begin(); pos != m_sect_infos.end(); 431*4bafceceSPaolo Severini ++pos, ++idx) { 432*4bafceceSPaolo Severini ostream << "[" << llvm::format_decimal(idx, 2) << "] "; 433*4bafceceSPaolo Severini ObjectFileWasm::DumpSectionHeader(ostream, *pos); 434*4bafceceSPaolo Severini } 435*4bafceceSPaolo Severini } 436