@@ -36,6 +36,41 @@ LLDB_PLUGIN_DEFINE(ObjectFileWasm)
3636static const uint32_t kWasmHeaderSize =
3737 sizeof(llvm::wasm::WasmMagic) + sizeof(llvm::wasm::WasmVersion);
3838
39+ // / Helper to read a 32-bit ULEB using LLDB's DataExtractor.
40+ static inline llvm::Expected<uint32_t > GetULEB32 (DataExtractor &data,
41+ lldb::offset_t &offset) {
42+ const uint64_t value = data.GetULEB128 (&offset);
43+ if (value > std::numeric_limits<uint32_t >::max ())
44+ return llvm::createStringError (" ULEB exceeds 32 bits" );
45+ return value;
46+ }
47+
48+ // / Helper to read a 32-bit ULEB using LLVM's DataExtractor.
49+ static inline llvm::Expected<uint32_t >
50+ GetULEB32 (llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
51+ const uint64_t value = data.getULEB128 (c);
52+ if (!c)
53+ return c.takeError ();
54+ if (value > std::numeric_limits<uint32_t >::max ())
55+ return llvm::createStringError (" ULEB exceeds 32 bits" );
56+ return value;
57+ }
58+
59+ // / Helper to read a Wasm string, whcih is encoded as a vector of UTF-8 codes.
60+ static inline llvm::Expected<std::string>
61+ GetWasmString (llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
62+ llvm::Expected<uint32_t > len = GetULEB32 (data, c);
63+ if (!len)
64+ return len.takeError ();
65+
66+ llvm::SmallVector<uint8_t , 32 > str_storage;
67+ data.getU8 (c, str_storage, *len);
68+ if (!c)
69+ return c.takeError ();
70+
71+ return std::string (toStringRef (llvm::ArrayRef (str_storage)));
72+ }
73+
3974// / Checks whether the data buffer starts with a valid Wasm module header.
4075static bool ValidateModuleHeader (const DataBufferSP &data_sp) {
4176 if (!data_sp || data_sp->GetByteSize () < kWasmHeaderSize )
@@ -51,32 +86,6 @@ static bool ValidateModuleHeader(const DataBufferSP &data_sp) {
5186 return version == llvm::wasm::WasmVersion;
5287}
5388
54- // FIXME: Use lldb::DataExtractor instead of llvm::DataExtractor.
55- static std::optional<std::string>
56- GetWasmString (llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
57- // A Wasm string is encoded as a vector of UTF-8 codes.
58- // Vectors are encoded with their u32 length followed by the element
59- // sequence.
60- uint64_t len = data.getULEB128 (c);
61- if (!c) {
62- consumeError (c.takeError ());
63- return std::nullopt ;
64- }
65-
66- if (len > std::numeric_limits<uint32_t >::max ()) {
67- return std::nullopt ;
68- }
69-
70- llvm::SmallVector<uint8_t , 32 > str_storage;
71- data.getU8 (c, str_storage, len);
72- if (!c) {
73- consumeError (c.takeError ());
74- return std::nullopt ;
75- }
76-
77- return std::string (toStringRef (llvm::ArrayRef (str_storage)));
78- }
79-
8089char ObjectFileWasm::ID;
8190
8291void ObjectFileWasm::Initialize () {
@@ -183,9 +192,12 @@ bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) {
183192 // identifying the custom section, followed by an uninterpreted sequence
184193 // of bytes.
185194 lldb::offset_t prev_offset = c.tell ();
186- std::optional<std::string> sect_name = GetWasmString (data, c);
187- if (!sect_name)
195+ llvm::Expected<std::string> sect_name = GetWasmString (data, c);
196+ if (!sect_name) {
197+ LLDB_LOG_ERROR (GetLog (LLDBLog::Object), sect_name.takeError (),
198+ " failed to parse section name: {0}" );
188199 return false ;
200+ }
189201
190202 if (payload_len < c.tell () - prev_offset)
191203 return false ;
@@ -255,26 +267,26 @@ ParseFunctions(SectionSP code_section_sp) {
255267 code_section_sp->GetSectionData (data);
256268 lldb::offset_t offset = 0 ;
257269
258- const uint64_t function_count = data. GetULEB128 (& offset);
259- if (function_count > std::numeric_limits< uint32_t >:: max () )
260- return llvm::createStringError ( " function count overflows uint32_t " );
270+ llvm::Expected< uint32_t > function_count = GetULEB32 (data, offset);
271+ if (! function_count)
272+ return function_count. takeError ( );
261273
262274 std::vector<AddressRange> functions;
263- functions.reserve (function_count);
275+ functions.reserve (* function_count);
264276
265- for (uint32_t i = 0 ; i < function_count; ++i) {
266- const uint64_t function_size = data. GetULEB128 (& offset);
267- if (function_size > std::numeric_limits< uint32_t >:: max () )
268- return llvm::createStringError ( " function size overflows uint32_t " );
277+ for (uint32_t i = 0 ; i < * function_count; ++i) {
278+ llvm::Expected< uint32_t > function_size = GetULEB32 (data, offset);
279+ if (! function_size)
280+ return function_size. takeError ( );
269281 // llvm-objdump considers the ULEB with the function size to be part of the
270282 // function. We can't do that here because that would break symbolic
271283 // breakpoints, as that address is never executed.
272- functions.emplace_back (code_section_sp, offset, function_size);
284+ functions.emplace_back (code_section_sp, offset, * function_size);
273285
274286 std::optional<lldb::offset_t > next_offset =
275- llvm::checkedAddUnsigned (offset, function_size);
287+ llvm::checkedAddUnsigned<lldb:: offset_t > (offset, * function_size);
276288 if (!next_offset)
277- return llvm::createStringError (" function offset overflows uint64_t " );
289+ return llvm::createStringError (" function offset overflows 64 bits " );
278290 offset = *next_offset;
279291 }
280292
@@ -295,44 +307,44 @@ ParseData(SectionSP data_section_sp) {
295307
296308 lldb::offset_t offset = 0 ;
297309
298- const uint64_t segment_count = data. GetULEB128 (& offset);
299- if (segment_count > std::numeric_limits< uint32_t >:: max () )
300- return llvm::createStringError ( " segment count overflows uint32_t " );
310+ llvm::Expected< uint32_t > segment_count = GetULEB32 (data, offset);
311+ if (! segment_count)
312+ return segment_count. takeError ( );
301313
302314 std::vector<WasmSegment> segments;
303- segments.reserve (segment_count);
315+ segments.reserve (* segment_count);
304316
305- for (uint32_t i = 0 ; i < segment_count; ++i) {
306- const uint64_t flags = data. GetULEB128 (& offset);
307- if (flags > std::numeric_limits< uint32_t >:: max () )
308- return llvm::createStringError ( " segment flags overflows uint32_t " );
317+ for (uint32_t i = 0 ; i < * segment_count; ++i) {
318+ llvm::Expected< uint32_t > flags = GetULEB32 (data, offset);
319+ if (! flags)
320+ return flags. takeError ( );
309321
310322 // Data segments have a mode that identifies them as either passive or
311323 // active. An active data segment copies its contents into a memory during
312324 // instantiation, as specified by a memory index and a constant expression
313325 // 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 " );
326+ if (* flags & llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) {
327+ llvm::Expected< uint32_t > memidx = GetULEB32 (data, offset);
328+ if (! memidx)
329+ return memidx. takeError ( );
318330 }
319331
320- if ((flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0 ) {
332+ if ((* flags & llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0 ) {
321333 // Skip over the constant expression.
322334 for (uint8_t b = 0 ; b != llvm::wasm::WASM_OPCODE_END;)
323335 b = data.GetU8 (&offset);
324336 }
325337
326- const uint64_t segment_size = data. GetULEB128 (& offset);
327- if (segment_size > std::numeric_limits< uint32_t >:: max () )
328- return llvm::createStringError ( " segment size overflows uint32_t " );
338+ llvm::Expected< uint32_t > segment_size = GetULEB32 (data, offset);
339+ if (! segment_size)
340+ return segment_size. takeError ( );
329341
330- segments.emplace_back (data_section_sp, offset, segment_size);
342+ segments.emplace_back (data_section_sp, offset, * segment_size);
331343
332344 std::optional<lldb::offset_t > next_offset =
333- llvm::checkedAddUnsigned (offset, segment_size);
345+ llvm::checkedAddUnsigned<lldb:: offset_t > (offset, * segment_size);
334346 if (!next_offset)
335- return llvm::createStringError (" segment offset overflows uint64_t " );
347+ return llvm::createStringError (" segment offset overflows 64 bits " );
336348 offset = *next_offset;
337349 }
338350
@@ -351,9 +363,9 @@ ParseNames(SectionSP name_section_sp,
351363 std::vector<Symbol> symbols;
352364 while (c && c.tell () < data.size ()) {
353365 const uint8_t type = data.getU8 (c);
354- const uint64_t size = data. getULEB128 ( c);
355- if (size > std::numeric_limits< uint32_t >:: max () )
356- return llvm::createStringError ( " size overflows uint32_t " );
366+ llvm::Expected< uint32_t > size = GetULEB32 (data, c);
367+ if (! size)
368+ return size. takeError ( );
357369
358370 switch (type) {
359371 case llvm::wasm::WASM_NAMES_FUNCTION: {
@@ -362,26 +374,34 @@ ParseNames(SectionSP name_section_sp,
362374 return llvm::createStringError (" function count overflows uint32_t" );
363375
364376 for (uint64_t i = 0 ; c && i < count; ++i) {
365- const uint64_t idx = data.getULEB128 (c);
366- const std::optional<std::string> name = GetWasmString (data, c);
367- if (!name || idx >= function_ranges.size ())
377+ llvm::Expected<uint32_t > idx = GetULEB32 (data, c);
378+ if (!idx)
379+ return idx.takeError ();
380+ llvm::Expected<std::string> name = GetWasmString (data, c);
381+ if (!name)
382+ return name.takeError ();
383+ if (*idx >= function_ranges.size ())
368384 continue ;
369385 symbols.emplace_back (
370386 symbols.size (), Mangled (*name), lldb::eSymbolTypeCode,
371387 /* external=*/ false , /* is_debug=*/ false , /* is_trampoline=*/ false ,
372- /* is_artificial=*/ false , function_ranges[idx],
388+ /* is_artificial=*/ false , function_ranges[* idx],
373389 /* size_is_valid=*/ true , /* contains_linker_annotations=*/ false ,
374390 /* flags=*/ 0 );
375391 }
376392 } break ;
377393 case llvm::wasm::WASM_NAMES_DATA_SEGMENT: {
378- const uint64_t count = data.getULEB128 (c);
379- if (count > std::numeric_limits<uint32_t >::max ())
380- return llvm::createStringError (" data count overflows uint32_t" );
381- for (uint64_t i = 0 ; c && i < count; ++i) {
382- const uint64_t idx = data.getULEB128 (c);
383- const std::optional<std::string> name = GetWasmString (data, c);
384- if (!name || idx >= segments.size ())
394+ llvm::Expected<uint32_t > count = GetULEB32 (data, c);
395+ if (!count)
396+ return count.takeError ();
397+ for (uint32_t i = 0 ; c && i < *count; ++i) {
398+ llvm::Expected<uint32_t > idx = GetULEB32 (data, c);
399+ if (!idx)
400+ return idx.takeError ();
401+ llvm::Expected<std::string> name = GetWasmString (data, c);
402+ if (!name)
403+ return name.takeError ();
404+ if (*idx >= segments.size ())
385405 continue ;
386406 // Update the segment name.
387407 segments[i].name = *name;
@@ -397,9 +417,10 @@ ParseNames(SectionSP name_section_sp,
397417 case llvm::wasm::WASM_NAMES_GLOBAL:
398418 case llvm::wasm::WASM_NAMES_LOCAL:
399419 default :
400- std::optional<uint64_t > offset = llvm::checkedAddUnsigned (c.tell (), size);
420+ std::optional<lldb::offset_t > offset =
421+ llvm::checkedAddUnsigned<lldb::offset_t >(c.tell (), *size);
401422 if (!offset)
402- return llvm::createStringError (" offset overflows uint64_t " );
423+ return llvm::createStringError (" offset overflows 64 bits " );
403424 c.seek (*offset);
404425 }
405426 }
@@ -636,11 +657,15 @@ std::optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() {
636657 const uint32_t kBufferSize = 1024 ;
637658 DataExtractor section_header_data =
638659 ReadImageData (sect_info.offset , kBufferSize );
660+
639661 llvm::DataExtractor data = section_header_data.GetAsLLVM ();
640662 llvm::DataExtractor::Cursor c (0 );
641- std::optional<std::string> symbols_url = GetWasmString (data, c);
642- if (symbols_url)
643- return FileSpec (*symbols_url);
663+ llvm::Expected<std::string> symbols_url = GetWasmString (data, c);
664+ if (!symbols_url) {
665+ llvm::consumeError (symbols_url.takeError ());
666+ return std::nullopt ;
667+ }
668+ return FileSpec (*symbols_url);
644669 }
645670 }
646671 return std::nullopt ;
0 commit comments