Skip to content

Commit 704654e

Browse files
dschuffJDevlieghere
authored andcommitted
[lldb][Wasm] Handle imports when parsing Wasm name sections (llvm#170960)
LLDB can use the wasm name section to populate its symbol table and get names for functions. However the index space used in the name section is the "function index space" which includes imported as well as locally defined functions. (cherry picked from commit 782f507)
1 parent 25517fe commit 704654e

File tree

4 files changed

+125
-38
lines changed

4 files changed

+125
-38
lines changed

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

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,41 @@ struct WasmFunction {
307307
uint32_t size = 0;
308308
};
309309

310+
static llvm::Expected<uint32_t> ParseImports(DataExtractor &import_data) {
311+
// Currently this function just returns the number of imported functions.
312+
// If we want to do anything with global names in the future, we'll also
313+
// need to know those.
314+
llvm::DataExtractor data = import_data.GetAsLLVM();
315+
llvm::DataExtractor::Cursor c(0);
316+
317+
llvm::Expected<uint32_t> count = GetULEB32(data, c);
318+
if (!count)
319+
return count.takeError();
320+
321+
uint32_t function_imports = 0;
322+
for (uint32_t i = 0; c && i < *count; ++i) {
323+
// We don't need module and field names, so we can just get them as raw
324+
// strings and discard.
325+
if (!GetWasmString(data, c))
326+
return llvm::createStringError("failed to parse module name");
327+
if (!GetWasmString(data, c))
328+
return llvm::createStringError("failed to parse field name");
329+
330+
uint8_t kind = data.getU8(c);
331+
if (kind == llvm::wasm::WASM_EXTERNAL_FUNCTION)
332+
function_imports++;
333+
334+
// For function imports, this is a type index. For others it's different.
335+
// We don't need it, just need to parse it to advance the cursor.
336+
data.getULEB128(c);
337+
}
338+
339+
if (!c)
340+
return c.takeError();
341+
342+
return function_imports;
343+
}
344+
310345
static llvm::Expected<std::vector<WasmFunction>>
311346
ParseFunctions(DataExtractor &data) {
312347
lldb::offset_t offset = 0;
@@ -410,7 +445,8 @@ static llvm::Expected<std::vector<WasmSegment>> ParseData(DataExtractor &data) {
410445
static llvm::Expected<std::vector<Symbol>>
411446
ParseNames(SectionSP code_section_sp, DataExtractor &name_data,
412447
const std::vector<WasmFunction> &functions,
413-
std::vector<WasmSegment> &segments) {
448+
std::vector<WasmSegment> &segments,
449+
uint32_t num_imported_functions) {
414450

415451
llvm::DataExtractor data = name_data.GetAsLLVM();
416452
llvm::DataExtractor::Cursor c(0);
@@ -434,15 +470,29 @@ ParseNames(SectionSP code_section_sp, DataExtractor &name_data,
434470
llvm::Expected<std::string> name = GetWasmString(data, c);
435471
if (!name)
436472
return name.takeError();
437-
if (*idx >= functions.size())
473+
if (*idx >= num_imported_functions + functions.size())
438474
continue;
439-
symbols.emplace_back(
440-
symbols.size(), *name, lldb::eSymbolTypeCode,
441-
/*external=*/false, /*is_debug=*/false, /*is_trampoline=*/false,
442-
/*is_artificial=*/false, code_section_sp,
443-
functions[i].section_offset, functions[i].size,
444-
/*size_is_valid=*/true, /*contains_linker_annotations=*/false,
445-
/*flags=*/0);
475+
476+
if (*idx < num_imported_functions) {
477+
symbols.emplace_back(symbols.size(), *name, lldb::eSymbolTypeCode,
478+
/*external=*/true, /*is_debug=*/false,
479+
/*is_trampoline=*/false,
480+
/*is_artificial=*/false,
481+
/*section_sp=*/lldb::SectionSP(),
482+
/*value=*/0, /*size=*/0,
483+
/*size_is_valid=*/false,
484+
/*contains_linker_annotations=*/false,
485+
/*flags=*/0);
486+
} else {
487+
const WasmFunction &func = functions[*idx - num_imported_functions];
488+
symbols.emplace_back(symbols.size(), *name, lldb::eSymbolTypeCode,
489+
/*external=*/false, /*is_debug=*/false,
490+
/*is_trampoline=*/false, /*is_artificial=*/false,
491+
code_section_sp, func.section_offset, func.size,
492+
/*size_is_valid=*/true,
493+
/*contains_linker_annotations=*/false,
494+
/*flags=*/0);
495+
}
446496
}
447497
} break;
448498
case llvm::wasm::WASM_NAMES_DATA_SEGMENT: {
@@ -590,6 +640,20 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
590640
}
591641
}
592642

643+
// Parse the import section. The number of functions is needed because the
644+
// function index space used in the name section includes imports.
645+
if (std::optional<section_info> info =
646+
GetSectionInfo(llvm::wasm::WASM_SEC_IMPORT)) {
647+
DataExtractor import_data = ReadImageData(info->offset, info->size);
648+
llvm::Expected<uint32_t> num_imports = ParseImports(import_data);
649+
if (!num_imports) {
650+
LLDB_LOG_ERROR(log, num_imports.takeError(),
651+
"Failed to parse Wasm import section: {0}");
652+
} else {
653+
m_num_imported_functions = *num_imports;
654+
}
655+
}
656+
593657
// Parse the data section.
594658
std::optional<section_info> data_info =
595659
GetSectionInfo(llvm::wasm::WASM_SEC_DATA);
@@ -609,7 +673,7 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
609673
DataExtractor names_data = ReadImageData(info->offset, info->size);
610674
llvm::Expected<std::vector<Symbol>> symbols = ParseNames(
611675
m_sections_up->FindSectionByType(lldb::eSectionTypeCode, false),
612-
names_data, functions, segments);
676+
names_data, functions, segments, m_num_imported_functions);
613677
if (!symbols) {
614678
LLDB_LOG_ERROR(log, symbols.takeError(),
615679
"Failed to parse Wasm names: {0}");

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class ObjectFileWasm : public ObjectFile {
146146
/// \}
147147

148148
std::vector<section_info> m_sect_infos;
149+
uint32_t m_num_imported_functions = 0;
149150
std::vector<Symbol> m_symbols;
150151
ArchSpec m_arch;
151152
UUID m_uuid;

lldb/test/Shell/Symtab/Inputs/simple.wasm.yaml

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# int j = 2;
1111
# return add(i, j);
1212
# }
13+
# Additional imports have been manually added and indexes adjusted after compiling
1314
--- !WASM
1415
FileHeader:
1516
Version: 0x1
@@ -29,6 +30,21 @@ Sections:
2930
ParamTypes: []
3031
ReturnTypes:
3132
- I32
33+
- Type: IMPORT
34+
Imports:
35+
- Module: env
36+
Field: foo
37+
Kind: FUNCTION
38+
SigIndex: 0
39+
- Module: env
40+
Field: another_import
41+
Kind: FUNCTION
42+
SigIndex: 0
43+
- Module: env
44+
Field: bar
45+
Kind: GLOBAL
46+
GlobalType: I32
47+
GlobalMutable: true
3248
- Type: FUNCTION
3349
FunctionTypes: [ 0, 1, 2, 1 ]
3450
- Type: TABLE
@@ -44,73 +60,73 @@ Sections:
4460
- Minimum: 0x2
4561
- Type: GLOBAL
4662
Globals:
47-
- Index: 0
63+
- Index: 1
4864
Type: I32
4965
Mutable: true
5066
InitExpr:
5167
Opcode: I32_CONST
5268
Value: 66576
53-
- Index: 1
69+
- Index: 2
5470
Type: I32
5571
Mutable: false
5672
InitExpr:
5773
Opcode: I32_CONST
5874
Value: 1036
59-
- Index: 2
75+
- Index: 3
6076
Type: I32
6177
Mutable: false
6278
InitExpr:
6379
Opcode: I32_CONST
6480
Value: 1024
65-
- Index: 3
81+
- Index: 4
6682
Type: I32
6783
Mutable: false
6884
InitExpr:
6985
Opcode: I32_CONST
7086
Value: 1040
71-
- Index: 4
87+
- Index: 5
7288
Type: I32
7389
Mutable: false
7490
InitExpr:
7591
Opcode: I32_CONST
7692
Value: 1040
77-
- Index: 5
93+
- Index: 6
7894
Type: I32
7995
Mutable: false
8096
InitExpr:
8197
Opcode: I32_CONST
8298
Value: 66576
83-
- Index: 6
99+
- Index: 7
84100
Type: I32
85101
Mutable: false
86102
InitExpr:
87103
Opcode: I32_CONST
88104
Value: 1024
89-
- Index: 7
105+
- Index: 8
90106
Type: I32
91107
Mutable: false
92108
InitExpr:
93109
Opcode: I32_CONST
94110
Value: 66576
95-
- Index: 8
111+
- Index: 9
96112
Type: I32
97113
Mutable: false
98114
InitExpr:
99115
Opcode: I32_CONST
100116
Value: 131072
101-
- Index: 9
117+
- Index: 10
102118
Type: I32
103119
Mutable: false
104120
InitExpr:
105121
Opcode: I32_CONST
106122
Value: 0
107-
- Index: 10
123+
- Index: 11
108124
Type: I32
109125
Mutable: false
110126
InitExpr:
111127
Opcode: I32_CONST
112128
Value: 1
113-
- Index: 11
129+
- Index: 12
114130
Type: I32
115131
Mutable: false
116132
InitExpr:
@@ -123,16 +139,16 @@ Sections:
123139
Index: 0
124140
- Name: __wasm_call_ctors
125141
Kind: FUNCTION
126-
Index: 0
142+
Index: 2
127143
- Name: add
128144
Kind: FUNCTION
129-
Index: 1
145+
Index: 3
130146
- Name: __original_main
131147
Kind: FUNCTION
132-
Index: 2
148+
Index: 4
133149
- Name: main
134150
Kind: FUNCTION
135-
Index: 3
151+
Index: 5
136152
- Name: str
137153
Kind: GLOBAL
138154
Index: 1
@@ -174,20 +190,20 @@ Sections:
174190
Index: 11
175191
- Type: CODE
176192
Functions:
177-
- Index: 0
193+
- Index: 2
178194
Locals: []
179195
Body: 0B
180-
- Index: 1
196+
- Index: 3
181197
Locals:
182198
- Type: I32
183199
Count: 1
184200
Body: 23808080800041106B21022002200036020C20022001360208200228020C20022802086A0F0B
185-
- Index: 2
201+
- Index: 4
186202
Locals:
187203
- Type: I32
188204
Count: 2
189205
Body: 23808080800041106B210020002480808080002000410036020C2000410136020820004102360204200028020820002802041081808080002101200041106A24808080800020010F0B
190-
- Index: 3
206+
- Index: 5
191207
Locals: []
192208
Body: 1082808080000F0B
193209
- Type: DATA
@@ -208,15 +224,19 @@ Sections:
208224
Name: name
209225
FunctionNames:
210226
- Index: 0
211-
Name: __wasm_call_ctors
227+
Name: foo
212228
- Index: 1
213-
Name: add
229+
Name: another_import
214230
- Index: 2
215-
Name: __original_main
231+
Name: __wasm_call_ctors
216232
- Index: 3
233+
Name: add
234+
- Index: 4
235+
Name: __original_main
236+
- Index: 5
217237
Name: main
218238
GlobalNames:
219-
- Index: 0
239+
- Index: 1
220240
Name: __stack_pointer
221241
DataSegmentNames:
222242
- Index: 0
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# RUN: yaml2obj %S/Inputs/simple.wasm.yaml -o %t.wasm
22

33
# RUN: %lldb %t.wasm -o 'image dump symtab' | FileCheck %s --check-prefix SYMTAB
4+
SYMTAB: Code 0x0000000000000000 0x0000000000000000 0x00000000 foo
5+
SYMTAB: Code 0x0000000000000000 0x0000000000000000 0x00000000 another_import
46
SYMTAB: Code 0x0000000000000002 0x0000000000000002 0x00000000 __wasm_call_ctors
57
SYMTAB: Code 0x0000000000000005 0x0000000000000029 0x00000000 add
68
SYMTAB: Code 0x000000000000002f 0x000000000000004c 0x00000000 __original_main
79
SYMTAB: Code 0x000000000000007c 0x0000000000000009 0x00000000 main
810

911
# RUN: %lldb %t.wasm -o 'image dump sections' | FileCheck %s --check-prefix SECTIONS
10-
SECTIONS: 0x0000000000000001 code [0x0000000000000000-0x0000000000000085) --- 0x000001a1 0x00000085 0x00000000 symtab-wasm.test.tmp.wasm.code
11-
SECTIONS: 0x0000000000000040 wasm-name --- 0x00000251 0x00000059 0x00000000 symtab-wasm.test.tmp.wasm.name
12-
SECTIONS: 0x0000000000000100 data [0x0000000000000400-0x0000000000000409) --- 0x00000233 0x00000009 0x00000000 symtab-wasm.test.tmp.wasm..rodata
13-
SECTIONS: 0x0000000000000200 data [0x000000000000040c-0x0000000000000410) --- 0x00000242 0x00000004 0x00000000 symtab-wasm.test.tmp.wasm..data
12+
SECTIONS: 0x0000000000000001 code [0x0000000000000000-0x0000000000000085) --- 0x000001d2 0x00000085 0x00000000 symtab-wasm.test.tmp.wasm.code
13+
SECTIONS: 0x0000000000000040 wasm-name --- 0x00000282 0x0000006e 0x00000000 symtab-wasm.test.tmp.wasm.name
14+
SECTIONS: 0x0000000000000100 data [0x0000000000000400-0x0000000000000409) --- 0x00000264 0x00000009 0x00000000 symtab-wasm.test.tmp.wasm..rodata
15+
SECTIONS: 0x0000000000000200 data [0x000000000000040c-0x0000000000000410) --- 0x00000273 0x00000004 0x00000000 symtab-wasm.test.tmp.wasm..data
1416

1517
# RUN: %lldb %t.wasm -o 'x/s 0x0000000000000400' | FileCheck %s --check-prefix STR
1618
STR: "data str"

0 commit comments

Comments
 (0)