summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/ObjectFile
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ObjectFile')
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp41
-rw-r--r--lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp35
-rw-r--r--lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h3
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp122
-rw-r--r--lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp329
-rw-r--r--lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h13
6 files changed, 292 insertions, 251 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index f69358de6a28..931baf5927a0 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -2037,6 +2037,19 @@ static char FindArmAarch64MappingSymbol(const char *symbol_name) {
return '\0';
}
+static char FindRISCVMappingSymbol(const char *symbol_name) {
+ if (!symbol_name)
+ return '\0';
+
+ if (strcmp(symbol_name, "$d") == 0) {
+ return 'd';
+ }
+ if (strcmp(symbol_name, "$x") == 0) {
+ return 'x';
+ }
+ return '\0';
+}
+
#define STO_MIPS_ISA (3 << 6)
#define STO_MICROMIPS (2 << 6)
#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
@@ -2102,6 +2115,12 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (!symbol_name)
symbol_name = "";
+ // Skip local symbols starting with ".L" because these are compiler
+ // generated local labels used for internal purposes (e.g. debugging,
+ // optimization) and are not relevant for symbol resolution or external
+ // linkage.
+ if (llvm::StringRef(symbol_name).starts_with(".L"))
+ continue;
// No need to add non-section symbols that have no names
if (symbol.getType() != STT_SECTION &&
(symbol_name == nullptr || symbol_name[0] == '\0'))
@@ -2190,7 +2209,6 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
int64_t symbol_value_offset = 0;
uint32_t additional_flags = 0;
-
if (arch.IsValid()) {
if (arch.GetMachine() == llvm::Triple::arm) {
if (symbol.getBinding() == STB_LOCAL) {
@@ -2235,6 +2253,27 @@ ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (mapping_symbol)
continue;
}
+ } else if (arch.GetTriple().isRISCV()) {
+ if (symbol.getBinding() == STB_LOCAL) {
+ char mapping_symbol = FindRISCVMappingSymbol(symbol_name);
+ if (symbol_type == eSymbolTypeCode) {
+ // Only handle $d and $x mapping symbols.
+ // Other mapping symbols are ignored as they don't affect address
+ // classification.
+ switch (mapping_symbol) {
+ case 'x':
+ // $x - marks a RISCV instruction sequence
+ address_class_map[symbol.st_value] = AddressClass::eCode;
+ break;
+ case 'd':
+ // $d - marks a RISCV data item sequence
+ address_class_map[symbol.st_value] = AddressClass::eData;
+ break;
+ }
+ }
+ if (mapping_symbol)
+ continue;
+ }
}
if (arch.GetMachine() == llvm::Triple::arm) {
diff --git a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
index cb8ba05d461d..69885aa53ca3 100644
--- a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
+++ b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/ADT/DenseSet.h"
@@ -233,6 +234,40 @@ void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {
}
}
+bool ObjectFileJSON::SetLoadAddress(Target &target, lldb::addr_t value,
+ bool value_is_offset) {
+ Log *log(GetLog(LLDBLog::DynamicLoader));
+ if (!m_sections_up)
+ return true;
+
+ addr_t slide = value;
+ if (!value_is_offset) {
+ addr_t lowest_addr = LLDB_INVALID_ADDRESS;
+ for (const SectionSP &section_sp : *m_sections_up) {
+ addr_t section_load_addr = section_sp->GetFileAddress();
+ lowest_addr = std::min(lowest_addr, section_load_addr);
+ }
+ if (lowest_addr == LLDB_INVALID_ADDRESS)
+ return false;
+ slide = value - lowest_addr;
+ }
+
+ // Apply slide to each section's file address.
+ for (const SectionSP &section_sp : *m_sections_up) {
+ addr_t section_load_addr = section_sp->GetFileAddress();
+ if (section_load_addr != LLDB_INVALID_ADDRESS) {
+ LLDB_LOGF(
+ log,
+ "ObjectFileJSON::SetLoadAddress section %s to load addr 0x%" PRIx64,
+ section_sp->GetName().AsCString(), section_load_addr + slide);
+ target.SetSectionLoadAddress(section_sp, section_load_addr + slide,
+ /*warn_multiple=*/true);
+ }
+ }
+
+ return true;
+}
+
bool ObjectFileJSON::MagicBytesMatch(DataBufferSP data_sp,
lldb::addr_t data_offset,
lldb::addr_t data_length) {
diff --git a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
index b72565f46886..029c8ff18893 100644
--- a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
+++ b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.h
@@ -86,6 +86,9 @@ public:
Strata CalculateStrata() override { return eStrataUser; }
+ bool SetLoadAddress(Target &target, lldb::addr_t value,
+ bool value_is_offset) override;
+
static bool MagicBytesMatch(lldb::DataBufferSP data_sp, lldb::addr_t offset,
lldb::addr_t length);
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index d7cb60e3f0c3..924e34053d41 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -2785,7 +2785,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
const char *symbol_name_non_abi_mangled = NULL;
SectionSP symbol_section;
- uint32_t symbol_byte_size = 0;
bool add_nlist = true;
bool is_debug = ((nlist.n_type & N_STAB) != 0);
bool demangled_is_synthesized = false;
@@ -3437,61 +3436,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (symbol_section) {
const addr_t section_file_addr =
symbol_section->GetFileAddress();
- if (symbol_byte_size == 0 &&
- function_starts_count > 0) {
- addr_t symbol_lookup_file_addr = nlist.n_value;
- // Do an exact address match for non-ARM addresses,
- // else get the closest since the symbol might be a
- // thumb symbol which has an address with bit zero
- // set
- FunctionStarts::Entry *func_start_entry =
- function_starts.FindEntry(symbol_lookup_file_addr,
- !is_arm);
- if (is_arm && func_start_entry) {
- // Verify that the function start address is the
- // symbol address (ARM) or the symbol address + 1
- // (thumb)
- if (func_start_entry->addr !=
- symbol_lookup_file_addr &&
- func_start_entry->addr !=
- (symbol_lookup_file_addr + 1)) {
- // Not the right entry, NULL it out...
- func_start_entry = NULL;
- }
- }
- if (func_start_entry) {
- func_start_entry->data = true;
-
- addr_t symbol_file_addr = func_start_entry->addr;
- uint32_t symbol_flags = 0;
- if (is_arm) {
- if (symbol_file_addr & 1)
- symbol_flags = MACHO_NLIST_ARM_SYMBOL_IS_THUMB;
- symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
- }
-
- const FunctionStarts::Entry *next_func_start_entry =
- function_starts.FindNextEntry(func_start_entry);
- const addr_t section_end_file_addr =
- section_file_addr +
- symbol_section->GetByteSize();
- if (next_func_start_entry) {
- addr_t next_symbol_file_addr =
- next_func_start_entry->addr;
- // Be sure the clear the Thumb address bit when
- // we calculate the size from the current and
- // next address
- if (is_arm)
- next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
- symbol_byte_size = std::min<lldb::addr_t>(
- next_symbol_file_addr - symbol_file_addr,
- section_end_file_addr - symbol_file_addr);
- } else {
- symbol_byte_size =
- section_end_file_addr - symbol_file_addr;
- }
- }
- }
symbol_value -= section_file_addr;
}
@@ -3620,9 +3564,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
}
sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc);
- if (symbol_byte_size > 0)
- sym[sym_idx].SetByteSize(symbol_byte_size);
-
if (demangled_is_synthesized)
sym[sym_idx].SetDemangledNameIsSynthesized(true);
++sym_idx;
@@ -3711,7 +3652,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
SymbolType type = eSymbolTypeInvalid;
SectionSP symbol_section;
- lldb::addr_t symbol_byte_size = 0;
bool add_nlist = true;
bool is_gsym = false;
bool demangled_is_synthesized = false;
@@ -4297,47 +4237,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (symbol_section) {
const addr_t section_file_addr = symbol_section->GetFileAddress();
- if (symbol_byte_size == 0 && function_starts_count > 0) {
- addr_t symbol_lookup_file_addr = nlist.n_value;
- // Do an exact address match for non-ARM addresses, else get the
- // closest since the symbol might be a thumb symbol which has an
- // address with bit zero set.
- FunctionStarts::Entry *func_start_entry =
- function_starts.FindEntry(symbol_lookup_file_addr, !is_arm);
- if (is_arm && func_start_entry) {
- // Verify that the function start address is the symbol address
- // (ARM) or the symbol address + 1 (thumb).
- if (func_start_entry->addr != symbol_lookup_file_addr &&
- func_start_entry->addr != (symbol_lookup_file_addr + 1)) {
- // Not the right entry, NULL it out...
- func_start_entry = nullptr;
- }
- }
- if (func_start_entry) {
- func_start_entry->data = true;
-
- addr_t symbol_file_addr = func_start_entry->addr;
- if (is_arm)
- symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
-
- const FunctionStarts::Entry *next_func_start_entry =
- function_starts.FindNextEntry(func_start_entry);
- const addr_t section_end_file_addr =
- section_file_addr + symbol_section->GetByteSize();
- if (next_func_start_entry) {
- addr_t next_symbol_file_addr = next_func_start_entry->addr;
- // Be sure the clear the Thumb address bit when we calculate the
- // size from the current and next address
- if (is_arm)
- next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
- symbol_byte_size = std::min<lldb::addr_t>(
- next_symbol_file_addr - symbol_file_addr,
- section_end_file_addr - symbol_file_addr);
- } else {
- symbol_byte_size = section_end_file_addr - symbol_file_addr;
- }
- }
- }
symbol_value -= section_file_addr;
}
@@ -4444,9 +4343,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
if (nlist.n_desc & N_WEAK_REF)
sym[sym_idx].SetIsWeak(true);
- if (symbol_byte_size > 0)
- sym[sym_idx].SetByteSize(symbol_byte_size);
-
if (demangled_is_synthesized)
sym[sym_idx].SetDemangledNameIsSynthesized(true);
@@ -4565,23 +4461,7 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
Address symbol_addr;
if (module_sp->ResolveFileAddress(symbol_file_addr, symbol_addr)) {
SectionSP symbol_section(symbol_addr.GetSection());
- uint32_t symbol_byte_size = 0;
if (symbol_section) {
- const addr_t section_file_addr = symbol_section->GetFileAddress();
- const FunctionStarts::Entry *next_func_start_entry =
- function_starts.FindNextEntry(func_start_entry);
- const addr_t section_end_file_addr =
- section_file_addr + symbol_section->GetByteSize();
- if (next_func_start_entry) {
- addr_t next_symbol_file_addr = next_func_start_entry->addr;
- if (is_arm)
- next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
- symbol_byte_size = std::min<lldb::addr_t>(
- next_symbol_file_addr - symbol_file_addr,
- section_end_file_addr - symbol_file_addr);
- } else {
- symbol_byte_size = section_end_file_addr - symbol_file_addr;
- }
sym[sym_idx].SetID(synthetic_sym_id++);
// Don't set the name for any synthetic symbols, the Symbol
// object will generate one if needed when the name is accessed
@@ -4593,8 +4473,6 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
add_symbol_addr(symbol_addr.GetFileAddress());
if (symbol_flags)
sym[sym_idx].SetFlags(symbol_flags);
- if (symbol_byte_size)
- sym[sym_idx].SetByteSize(symbol_byte_size);
++sym_idx;
}
}
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 777b20e9bb0f..492b44186720 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -71,6 +71,47 @@ GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
return std::string(toStringRef(llvm::ArrayRef(str_storage)));
}
+/// An "init expr" refers to a constant expression used to determine the initial
+/// value of certain elements within a module during instantiation. These
+/// expressions are restricted to operations that can be evaluated at module
+/// instantiation time. Currently we only support simple constant opcodes.
+static lldb::offset_t GetWasmOffsetFromInitExpr(DataExtractor &data,
+ lldb::offset_t &offset) {
+ lldb::offset_t init_expr_offset = LLDB_INVALID_OFFSET;
+
+ uint8_t opcode = data.GetU8(&offset);
+ switch (opcode) {
+ case llvm::wasm::WASM_OPCODE_I32_CONST:
+ case llvm::wasm::WASM_OPCODE_I64_CONST:
+ init_expr_offset = data.GetSLEB128(&offset);
+ break;
+ case llvm::wasm::WASM_OPCODE_GLOBAL_GET:
+ init_expr_offset = data.GetULEB128(&offset);
+ break;
+ case llvm::wasm::WASM_OPCODE_F32_CONST:
+ case llvm::wasm::WASM_OPCODE_F64_CONST:
+ // Not a meaningful offset.
+ data.GetFloat(&offset);
+ break;
+ case llvm::wasm::WASM_OPCODE_REF_NULL:
+ // Not a meaningful offset.
+ data.GetULEB128(&offset);
+ break;
+ }
+
+ // Make sure the opcodes we read aren't part of an extended init expr.
+ opcode = data.GetU8(&offset);
+ if (opcode == llvm::wasm::WASM_OPCODE_END)
+ return init_expr_offset;
+
+ // Extended init expressions are not supported, but we still have to parse
+ // them to skip over them and read the next segment.
+ do {
+ opcode = data.GetU8(&offset);
+ } while (opcode != llvm::wasm::WASM_OPCODE_END);
+ return LLDB_INVALID_OFFSET;
+}
+
/// Checks whether the data buffer starts with a valid Wasm module header.
static bool ValidateModuleHeader(const DataBufferSP &data_sp) {
if (!data_sp || data_sp->GetByteSize() < kWasmHeaderSize)
@@ -261,17 +302,20 @@ bool ObjectFileWasm::ParseHeader() {
return true;
}
-static llvm::Expected<std::vector<AddressRange>>
-ParseFunctions(SectionSP code_section_sp) {
- DataExtractor data;
- code_section_sp->GetSectionData(data);
+struct WasmFunction {
+ lldb::offset_t section_offset = LLDB_INVALID_OFFSET;
+ uint32_t size = 0;
+};
+
+static llvm::Expected<std::vector<WasmFunction>>
+ParseFunctions(DataExtractor &data) {
lldb::offset_t offset = 0;
llvm::Expected<uint32_t> function_count = GetULEB32(data, offset);
if (!function_count)
return function_count.takeError();
- std::vector<AddressRange> functions;
+ std::vector<WasmFunction> functions;
functions.reserve(*function_count);
for (uint32_t i = 0; i < *function_count; ++i) {
@@ -281,7 +325,7 @@ ParseFunctions(SectionSP code_section_sp) {
// llvm-objdump considers the ULEB with the function size to be part of the
// function. We can't do that here because that would break symbolic
// breakpoints, as that address is never executed.
- functions.emplace_back(code_section_sp, offset, *function_size);
+ functions.push_back({offset, *function_size});
std::optional<lldb::offset_t> next_offset =
llvm::checkedAddUnsigned<lldb::offset_t>(offset, *function_size);
@@ -294,17 +338,22 @@ ParseFunctions(SectionSP code_section_sp) {
}
struct WasmSegment {
- WasmSegment(SectionSP section_sp, lldb::offset_t offset, uint32_t size)
- : address_range(section_sp, offset, size) {};
+ enum SegmentType {
+ Active,
+ Passive,
+ };
+
std::string name;
- AddressRange address_range;
-};
+ SegmentType type = Passive;
+ lldb::offset_t section_offset = LLDB_INVALID_OFFSET;
+ uint32_t size = 0;
+ uint32_t memory_index = 0;
+ lldb::offset_t init_expr_offset = 0;
-static llvm::Expected<std::vector<WasmSegment>>
-ParseData(SectionSP data_section_sp) {
- DataExtractor data;
- data_section_sp->GetSectionData(data);
+ lldb::offset_t GetFileOffset() const { return section_offset & 0xffffffff; }
+};
+static llvm::Expected<std::vector<WasmSegment>> ParseData(DataExtractor &data) {
lldb::offset_t offset = 0;
llvm::Expected<uint32_t> segment_count = GetULEB32(data, offset);
@@ -319,27 +368,34 @@ ParseData(SectionSP data_section_sp) {
if (!flags)
return flags.takeError();
+ WasmSegment segment;
+
// Data segments have a mode that identifies them as either passive or
// active. An active data segment copies its contents into a memory during
// instantiation, as specified by a memory index and a constant expression
// defining an offset into that memory.
+ segment.type = (*flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE)
+ ? WasmSegment::Passive
+ : WasmSegment::Active;
+
if (*flags & llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) {
+ assert(segment.type == WasmSegment::Active);
llvm::Expected<uint32_t> memidx = GetULEB32(data, offset);
if (!memidx)
return memidx.takeError();
+ segment.memory_index = *memidx;
}
- if ((*flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
- // Skip over the constant expression.
- for (uint8_t b = 0; b != llvm::wasm::WASM_OPCODE_END;)
- b = data.GetU8(&offset);
- }
+ if (segment.type == WasmSegment::Active)
+ segment.init_expr_offset = GetWasmOffsetFromInitExpr(data, offset);
llvm::Expected<uint32_t> segment_size = GetULEB32(data, offset);
if (!segment_size)
return segment_size.takeError();
- segments.emplace_back(data_section_sp, offset, *segment_size);
+ segment.section_offset = offset;
+ segment.size = *segment_size;
+ segments.push_back(segment);
std::optional<lldb::offset_t> next_offset =
llvm::checkedAddUnsigned<lldb::offset_t>(offset, *segment_size);
@@ -352,13 +408,11 @@ ParseData(SectionSP data_section_sp) {
}
static llvm::Expected<std::vector<Symbol>>
-ParseNames(SectionSP name_section_sp,
- const std::vector<AddressRange> &function_ranges,
+ParseNames(SectionSP code_section_sp, DataExtractor &name_data,
+ const std::vector<WasmFunction> &functions,
std::vector<WasmSegment> &segments) {
- DataExtractor name_section_data;
- name_section_sp->GetSectionData(name_section_data);
- llvm::DataExtractor data = name_section_data.GetAsLLVM();
+ llvm::DataExtractor data = name_data.GetAsLLVM();
llvm::DataExtractor::Cursor c(0);
std::vector<Symbol> symbols;
while (c && c.tell() < data.size()) {
@@ -380,12 +434,13 @@ ParseNames(SectionSP name_section_sp,
llvm::Expected<std::string> name = GetWasmString(data, c);
if (!name)
return name.takeError();
- if (*idx >= function_ranges.size())
+ if (*idx >= functions.size())
continue;
symbols.emplace_back(
- symbols.size(), Mangled(*name), lldb::eSymbolTypeCode,
+ symbols.size(), *name, lldb::eSymbolTypeCode,
/*external=*/false, /*is_debug=*/false, /*is_trampoline=*/false,
- /*is_artificial=*/false, function_ranges[*idx],
+ /*is_artificial=*/false, code_section_sp,
+ functions[i].section_offset, functions[i].size,
/*size_is_valid=*/true, /*contains_linker_annotations=*/false,
/*flags=*/0);
}
@@ -405,12 +460,6 @@ ParseNames(SectionSP name_section_sp,
continue;
// Update the segment name.
segments[i].name = *name;
- symbols.emplace_back(
- symbols.size(), Mangled(*name), lldb::eSymbolTypeData,
- /*external=*/false, /*is_debug=*/false, /*is_trampoline=*/false,
- /*is_artificial=*/false, segments[i].address_range,
- /*size_is_valid=*/true, /*contains_linker_annotations=*/false,
- /*flags=*/0);
}
} break;
@@ -432,80 +481,11 @@ ParseNames(SectionSP name_section_sp,
}
void ObjectFileWasm::ParseSymtab(Symtab &symtab) {
- assert(m_sections_up && "sections must be parsed");
- Log *log = GetLog(LLDBLog::Object);
-
- // The name section contains names and indexes. First parse the data from the
- // relevant sections so we can access it by its index.
- std::vector<AddressRange> functions;
- std::vector<WasmSegment> segments;
-
- // Parse the code section.
- if (SectionSP code_section_sp =
- m_sections_up->FindSectionByType(lldb::eSectionTypeCode, false)) {
- llvm::Expected<std::vector<AddressRange>> maybe_functions =
- ParseFunctions(code_section_sp);
- if (!maybe_functions) {
- LLDB_LOG_ERROR(log, maybe_functions.takeError(),
- "Failed to parse Wasm code section: {0}");
- return;
- }
- functions = *maybe_functions;
- }
-
- // Parse the data section.
- SectionSP data_section_sp =
- m_sections_up->FindSectionByType(lldb::eSectionTypeData, false);
- if (data_section_sp) {
- llvm::Expected<std::vector<WasmSegment>> maybe_segments =
- ParseData(data_section_sp);
- if (!maybe_segments) {
- LLDB_LOG_ERROR(log, maybe_segments.takeError(),
- "Failed to parse Wasm data section: {0}");
- return;
- }
- segments = *maybe_segments;
- }
-
- // Parse the name section.
- SectionSP name_section_sp =
- m_sections_up->FindSectionByType(lldb::eSectionTypeWasmName, false);
- if (!name_section_sp) {
- LLDB_LOG(log, "Failed to parse Wasm symbol table: no names section");
- return;
- }
-
- llvm::Expected<std::vector<Symbol>> symbols =
- ParseNames(name_section_sp, functions, segments);
- if (!symbols) {
- LLDB_LOG_ERROR(log, symbols.takeError(), "Failed to parse Wasm names: {0}");
- return;
- }
-
- for (const Symbol &symbol : *symbols)
+ for (const Symbol &symbol : m_symbols)
symtab.AddSymbol(symbol);
- lldb::user_id_t segment_id = 0;
- for (const WasmSegment &segment : segments) {
- const lldb::addr_t segment_addr =
- segment.address_range.GetBaseAddress().GetFileAddress();
- const size_t segment_size = segment.address_range.GetByteSize();
- SectionSP segment_sp = std::make_shared<Section>(
- /*parent_section_sp=*/data_section_sp, GetModule(),
- /*obj_file=*/this,
- ++segment_id << 8, // 1-based segment index, shifted by 8 bits to avoid
- // collision with section IDs.
- ConstString(segment.name), eSectionTypeData,
- /*file_vm_addr=*/segment_addr,
- /*vm_size=*/segment_size,
- /*file_offset=*/segment_addr,
- /*file_size=*/segment_size,
- /*log2align=*/0, /*flags=*/0);
- m_sections_up->AddSection(segment_sp);
- GetModule()->GetSectionList()->AddSection(segment_sp);
- }
-
symtab.Finalize();
+ m_symbols.clear();
}
static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
@@ -516,7 +496,27 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
return eSectionTypeOther;
}
+std::optional<ObjectFileWasm::section_info>
+ObjectFileWasm::GetSectionInfo(uint32_t section_id) {
+ for (const section_info &sect_info : m_sect_infos) {
+ if (sect_info.id == section_id)
+ return sect_info;
+ }
+ return std::nullopt;
+}
+
+std::optional<ObjectFileWasm::section_info>
+ObjectFileWasm::GetSectionInfo(llvm::StringRef section_name) {
+ for (const section_info &sect_info : m_sect_infos) {
+ if (sect_info.name == section_name)
+ return sect_info;
+ }
+ return std::nullopt;
+}
+
void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
+ Log *log = GetLog(LLDBLog::Object);
+
if (m_sections_up)
return;
@@ -530,7 +530,7 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
SectionType section_type = eSectionTypeOther;
ConstString section_name;
offset_t file_offset = sect_info.offset & 0xffffffff;
- addr_t vm_addr = file_offset;
+ addr_t vm_addr = sect_info.offset;
size_t vm_size = sect_info.size;
if (llvm::wasm::WASM_SEC_CODE == sect_info.id) {
@@ -542,9 +542,6 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
// For this reason Section::GetFileAddress() must return zero for the
// Code section.
vm_addr = 0;
- } else if (llvm::wasm::WASM_SEC_DATA == sect_info.id) {
- section_type = eSectionTypeData;
- section_name = ConstString("data");
} else {
section_type = GetSectionTypeFromName(sect_info.name.GetStringRef());
if (section_type == eSectionTypeOther)
@@ -556,23 +553,107 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
}
}
- SectionSP section_sp(
- new Section(GetModule(), // Module to which this section belongs.
- this, // ObjectFile to which this section belongs and
- // should read section data from.
- section_type, // Section ID.
- section_name, // Section name.
- section_type, // Section type.
- vm_addr, // VM address.
- vm_size, // VM size in bytes of this section.
- file_offset, // Offset of this section in the file.
- sect_info.size, // Size of the section as found in the file.
- 0, // Alignment of the section
- 0, // Flags for this section.
- 1)); // Number of host bytes per target byte
+ SectionSP section_sp = std::make_shared<Section>(
+ GetModule(), // Module to which this section belongs.
+ this, // ObjectFile to which this section belongs and
+ // should read section data from.
+ section_type, // Section ID.
+ section_name, // Section name.
+ section_type, // Section type.
+ vm_addr, // VM address.
+ vm_size, // VM size in bytes of this section.
+ file_offset, // Offset of this section in the file.
+ sect_info.size, // Size of the section as found in the file.
+ 0, // Alignment of the section
+ 0, // Flags for this section.
+ 1); // Number of host bytes per target byte
m_sections_up->AddSection(section_sp);
unified_section_list.AddSection(section_sp);
}
+
+ // The name section contains names and indexes. First parse the data from the
+ // relevant sections so we can access it by its index.
+ std::vector<WasmFunction> functions;
+ std::vector<WasmSegment> segments;
+
+ // Parse the code section.
+ if (std::optional<section_info> info =
+ GetSectionInfo(llvm::wasm::WASM_SEC_CODE)) {
+ DataExtractor code_data = ReadImageData(info->offset, info->size);
+ llvm::Expected<std::vector<WasmFunction>> maybe_functions =
+ ParseFunctions(code_data);
+ if (!maybe_functions) {
+ LLDB_LOG_ERROR(log, maybe_functions.takeError(),
+ "Failed to parse Wasm code section: {0}");
+ } else {
+ functions = *maybe_functions;
+ }
+ }
+
+ // Parse the data section.
+ std::optional<section_info> data_info =
+ GetSectionInfo(llvm::wasm::WASM_SEC_DATA);
+ if (data_info) {
+ DataExtractor data_data = ReadImageData(data_info->offset, data_info->size);
+ llvm::Expected<std::vector<WasmSegment>> maybe_segments =
+ ParseData(data_data);
+ if (!maybe_segments) {
+ LLDB_LOG_ERROR(log, maybe_segments.takeError(),
+ "Failed to parse Wasm data section: {0}");
+ } else {
+ segments = *maybe_segments;
+ }
+ }
+
+ if (std::optional<section_info> info = GetSectionInfo("name")) {
+ DataExtractor names_data = ReadImageData(info->offset, info->size);
+ llvm::Expected<std::vector<Symbol>> symbols = ParseNames(
+ m_sections_up->FindSectionByType(lldb::eSectionTypeCode, false),
+ names_data, functions, segments);
+ if (!symbols) {
+ LLDB_LOG_ERROR(log, symbols.takeError(),
+ "Failed to parse Wasm names: {0}");
+ } else {
+ m_symbols = *symbols;
+ }
+ }
+
+ lldb::user_id_t segment_id = 0;
+ for (const WasmSegment &segment : segments) {
+ if (segment.type == WasmSegment::Active) {
+ // FIXME: Support segments with a memory index.
+ if (segment.memory_index != 0) {
+ LLDB_LOG(log, "Skipping segment {0}: non-zero memory index is "
+ "currently unsupported");
+ continue;
+ }
+
+ if (segment.init_expr_offset == LLDB_INVALID_OFFSET) {
+ LLDB_LOG(log, "Skipping segment {0}: unsupported init expression");
+ continue;
+ }
+ }
+
+ const lldb::addr_t file_vm_addr =
+ segment.type == WasmSegment::Active
+ ? segment.init_expr_offset
+ : data_info->offset + segment.section_offset;
+ const lldb::offset_t file_offset =
+ data_info->GetFileOffset() + segment.GetFileOffset();
+ SectionSP segment_sp = std::make_shared<Section>(
+ GetModule(),
+ /*obj_file=*/this,
+ ++segment_id << 8, // 1-based segment index, shifted by 8 bits to avoid
+ // collision with section IDs.
+ ConstString(segment.name), eSectionTypeData,
+ /*file_vm_addr=*/file_vm_addr,
+ /*vm_size=*/segment.size,
+ /*file_offset=*/file_offset,
+ /*file_size=*/segment.size,
+ /*log2align=*/0, /*flags=*/0);
+ m_sections_up->AddSection(segment_sp);
+ GetModule()->GetSectionList()->AddSection(segment_sp);
+ }
}
bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address,
@@ -697,7 +778,7 @@ void ObjectFileWasm::Dump(Stream *s) {
}
void ObjectFileWasm::DumpSectionHeader(llvm::raw_ostream &ostream,
- const section_info_t &sh) {
+ const section_info &sh) {
ostream << llvm::left_justify(sh.name.GetStringRef(), 16) << " "
<< llvm::format_hex(sh.offset, 10) << " "
<< llvm::format_hex(sh.size, 10) << " " << llvm::format_hex(sh.id, 6)
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
index 531b5f0437a4..86ecbf26803c 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
@@ -128,20 +128,25 @@ private:
/// Read a range of bytes from the Wasm module.
DataExtractor ReadImageData(lldb::offset_t offset, uint32_t size);
- typedef struct section_info {
+ struct section_info {
lldb::offset_t offset;
uint32_t size;
uint32_t id;
ConstString name;
- } section_info_t;
+ lldb::offset_t GetFileOffset() const { return offset & 0xffffffff; }
+ };
+
+ std::optional<section_info> GetSectionInfo(uint32_t section_id);
+ std::optional<section_info> GetSectionInfo(llvm::StringRef section_name);
/// Wasm section header dump routines.
/// \{
- void DumpSectionHeader(llvm::raw_ostream &ostream, const section_info_t &sh);
+ void DumpSectionHeader(llvm::raw_ostream &ostream, const section_info &sh);
void DumpSectionHeaders(llvm::raw_ostream &ostream);
/// \}
- std::vector<section_info_t> m_sect_infos;
+ std::vector<section_info> m_sect_infos;
+ std::vector<Symbol> m_symbols;
ArchSpec m_arch;
UUID m_uuid;
};