Skip to content

Commit 8bd9897

Browse files
authored
[lldb] Create sections for Wasm segments (#153634)
This is a continuation of #153494. In a WebAssembly file, the "name" section contains names for the segments in the data section (WASM_NAMES_DATA_SEGMENT). We already parse these as symbols, and with this PR, we now also create sub-sections for each of the segments.
1 parent 0f34360 commit 8bd9897

File tree

2 files changed

+78
-26
lines changed

2 files changed

+78
-26
lines changed

lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,14 @@ ParseFunctions(SectionSP code_section_sp) {
281281
return functions;
282282
}
283283

284-
static llvm::Expected<std::vector<AddressRange>>
284+
struct WasmSegment {
285+
WasmSegment(SectionSP section_sp, lldb::offset_t offset, uint32_t size)
286+
: address_range(section_sp, offset, size) {};
287+
std::string name;
288+
AddressRange address_range;
289+
};
290+
291+
static llvm::Expected<std::vector<WasmSegment>>
285292
ParseData(SectionSP data_section_sp) {
286293
DataExtractor data;
287294
data_section_sp->GetSectionData(data);
@@ -292,16 +299,32 @@ ParseData(SectionSP data_section_sp) {
292299
if (segment_count > std::numeric_limits<uint32_t>::max())
293300
return llvm::createStringError("segment count overflows uint32_t");
294301

295-
std::vector<AddressRange> segments;
302+
std::vector<WasmSegment> segments;
296303
segments.reserve(segment_count);
297304

298305
for (uint32_t i = 0; i < segment_count; ++i) {
299306
const uint64_t flags = data.GetULEB128(&offset);
300307
if (flags > std::numeric_limits<uint32_t>::max())
301308
return llvm::createStringError("segment flags overflows uint32_t");
302309

310+
// Data segments have a mode that identifies them as either passive or
311+
// active. An active data segment copies its contents into a memory during
312+
// instantiation, as specified by a memory index and a constant expression
313+
// defining an offset into that memory.
314+
if (flags & llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) {
315+
const uint64_t memidx = data.GetULEB128(&offset);
316+
if (memidx > std::numeric_limits<uint32_t>::max())
317+
return llvm::createStringError("memidx overflows uint32_t");
318+
}
319+
320+
if ((flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
321+
// Skip over the constant expression.
322+
for (uint8_t b = 0; b != llvm::wasm::WASM_OPCODE_END;)
323+
b = data.GetU8(&offset);
324+
}
325+
303326
const uint64_t segment_size = data.GetULEB128(&offset);
304-
if (flags > std::numeric_limits<uint32_t>::max())
327+
if (segment_size > std::numeric_limits<uint32_t>::max())
305328
return llvm::createStringError("segment size overflows uint32_t");
306329

307330
segments.emplace_back(data_section_sp, offset, segment_size);
@@ -319,7 +342,7 @@ ParseData(SectionSP data_section_sp) {
319342
static llvm::Expected<std::vector<Symbol>>
320343
ParseNames(SectionSP name_section_sp,
321344
const std::vector<AddressRange> &function_ranges,
322-
const std::vector<AddressRange> &segment_ranges) {
345+
std::vector<WasmSegment> &segments) {
323346
DataExtractor name_section_data;
324347
name_section_sp->GetSectionData(name_section_data);
325348

@@ -358,12 +381,14 @@ ParseNames(SectionSP name_section_sp,
358381
for (uint64_t i = 0; c && i < count; ++i) {
359382
const uint64_t idx = data.getULEB128(c);
360383
const std::optional<std::string> name = GetWasmString(data, c);
361-
if (!name || idx >= segment_ranges.size())
384+
if (!name || idx >= segments.size())
362385
continue;
386+
// Update the segment name.
387+
segments[i].name = *name;
363388
symbols.emplace_back(
364389
symbols.size(), Mangled(*name), lldb::eSymbolTypeData,
365390
/*external=*/false, /*is_debug=*/false, /*is_trampoline=*/false,
366-
/*is_artificial=*/false, segment_ranges[idx],
391+
/*is_artificial=*/false, segments[i].address_range,
367392
/*size_is_valid=*/true, /*contains_linker_annotations=*/false,
368393
/*flags=*/0);
369394
}
@@ -391,33 +416,34 @@ void ObjectFileWasm::ParseSymtab(Symtab &symtab) {
391416

392417
// The name section contains names and indexes. First parse the data from the
393418
// relevant sections so we can access it by its index.
394-
std::vector<AddressRange> function_ranges;
395-
std::vector<AddressRange> segment_ranges;
419+
std::vector<AddressRange> functions;
420+
std::vector<WasmSegment> segments;
396421

397422
// Parse the code section.
398423
if (SectionSP code_section_sp =
399424
m_sections_up->FindSectionByType(lldb::eSectionTypeCode, false)) {
400-
llvm::Expected<std::vector<AddressRange>> functions =
425+
llvm::Expected<std::vector<AddressRange>> maybe_functions =
401426
ParseFunctions(code_section_sp);
402-
if (!functions) {
403-
LLDB_LOG_ERROR(log, functions.takeError(),
427+
if (!maybe_functions) {
428+
LLDB_LOG_ERROR(log, maybe_functions.takeError(),
404429
"Failed to parse Wasm code section: {0}");
405430
return;
406431
}
407-
function_ranges = *functions;
432+
functions = *maybe_functions;
408433
}
409434

410435
// Parse the data section.
411-
if (SectionSP data_section_sp =
412-
m_sections_up->FindSectionByType(lldb::eSectionTypeData, false)) {
413-
llvm::Expected<std::vector<AddressRange>> segments =
436+
SectionSP data_section_sp =
437+
m_sections_up->FindSectionByType(lldb::eSectionTypeData, false);
438+
if (data_section_sp) {
439+
llvm::Expected<std::vector<WasmSegment>> maybe_segments =
414440
ParseData(data_section_sp);
415-
if (!segments) {
416-
LLDB_LOG_ERROR(log, segments.takeError(),
441+
if (!maybe_segments) {
442+
LLDB_LOG_ERROR(log, maybe_segments.takeError(),
417443
"Failed to parse Wasm data section: {0}");
418444
return;
419445
}
420-
segment_ranges = *segments;
446+
segments = *maybe_segments;
421447
}
422448

423449
// Parse the name section.
@@ -429,7 +455,7 @@ void ObjectFileWasm::ParseSymtab(Symtab &symtab) {
429455
}
430456

431457
llvm::Expected<std::vector<Symbol>> symbols =
432-
ParseNames(name_section_sp, function_ranges, segment_ranges);
458+
ParseNames(name_section_sp, functions, segments);
433459
if (!symbols) {
434460
LLDB_LOG_ERROR(log, symbols.takeError(), "Failed to parse Wasm names: {0}");
435461
return;
@@ -438,6 +464,26 @@ void ObjectFileWasm::ParseSymtab(Symtab &symtab) {
438464
for (const Symbol &symbol : *symbols)
439465
symtab.AddSymbol(symbol);
440466

467+
lldb::user_id_t segment_id = 0;
468+
for (const WasmSegment &segment : segments) {
469+
const lldb::addr_t segment_addr =
470+
segment.address_range.GetBaseAddress().GetFileAddress();
471+
const size_t segment_size = segment.address_range.GetByteSize();
472+
SectionSP segment_sp = std::make_shared<Section>(
473+
/*parent_section_sp=*/data_section_sp, GetModule(),
474+
/*obj_file=*/this,
475+
++segment_id << 8, // 1-based segment index, shifted by 8 bits to avoid
476+
// collision with section IDs.
477+
ConstString(segment.name), eSectionTypeData,
478+
/*file_vm_addr=*/segment_addr,
479+
/*vm_size=*/segment_size,
480+
/*file_offset=*/segment_addr,
481+
/*file_size=*/segment_size,
482+
/*log2align=*/0, /*flags=*/0);
483+
m_sections_up->AddSection(segment_sp);
484+
GetModule()->GetSectionList()->AddSection(segment_sp);
485+
}
486+
441487
symtab.Finalize();
442488
}
443489

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
# RUN: yaml2obj %S/Inputs/simple.wasm.yaml -o %t.wasm
2-
# RUN: %lldb %t.wasm -o 'image dump symtab'
2+
# RUN: %lldb %t.wasm -o 'image dump symtab' -o 'image dump sections' | FileCheck %s
33

4-
# CHECK: Code 0x0000000000000002 0x0000000000000002 {{.*}} __wasm_call_ctors
5-
# CHECK: Code 0x0000000000000005 0x0000000000000029 {{.*}} add
6-
# CHECK: Code 0x000000000000002f 0x000000000000004c {{.*}} __original_main
7-
# CHECK: Code 0x000000000000007c 0x0000000000000009 {{.*}} main
8-
# CHECK: Data 0x000000000000022f 0x0000000000000041 {{.*}} .rodata
9-
# CHECK: Data 0x0000000000000270 0x0000000000000000 {{.*}} .data
4+
CHECK: Code 0x0000000000000002 0x0000000000000002 0x00000000 __wasm_call_ctors
5+
CHECK: Code 0x0000000000000005 0x0000000000000029 0x00000000 add
6+
CHECK: Code 0x000000000000002f 0x000000000000004c 0x00000000 __original_main
7+
CHECK: Code 0x000000000000007c 0x0000000000000009 0x00000000 main
8+
CHECK: Data 0x0000000000000233 0x0000000000000009 0x00000000 .rodata
9+
CHECK: Data 0x0000000000000242 0x0000000000000004 0x00000000 .data
10+
11+
CHECK: 0x0000000000000001 code {{.*}} 0x000001a1 0x00000085 0x00000000 symtab-wasm.test.tmp.wasm.code
12+
CHECK: 0x0000000000000003 data {{.*}} 0x0000022c 0x0000001a 0x00000000 symtab-wasm.test.tmp.wasm.data
13+
CHECK: 0x0000000000000040 wasm-name {{.*}} 0x00000251 0x00000059 0x00000000 symtab-wasm.test.tmp.wasm.name
14+
CHECK: 0x0000000000000100 data {{.*}} 0x00000233 0x00000009 0x00000000 symtab-wasm.test.tmp.wasm.data..rodata
15+
CHECK: 0x0000000000000200 data {{.*}} 0x00000242 0x00000004 0x00000000 symtab-wasm.test.tmp.wasm.data..data

0 commit comments

Comments
 (0)