flutter 如何修复WSL ubuntu dart内存Map快照问题?

z9ju0rcb  于 2023-05-19  发布在  Flutter
关注(0)|答案(1)|浏览(220)

所以我尝试在windows10上通过wsl沿着dart运行flutter github repository。但我一直收到这个错误

../../runtime/bin/snapshot_utils.cc: 143: error: Failed to memory map snapshot: /usr/lib/dart/bin/snapshots/dartdev.dart.snapshot

version=2.15.1 (stable) (Unknown timestamp) on "linux_x64"
pid=2051, thread=2054, isolate_group=(nil)((nil)), isolate=(nil)((nil))
isolate_instructions=0, vm_instructions=7fed37fef680
  pc 0x00007fed3824efcc fp 0x00007fed3575fb90 dart::Profiler::DumpStackTrace(void*)+0x7c
  pc 0x00007fed37fef834 fp 0x00007fed3575fc70 dart::Assert::Fail(char const*, ...) const+0x84
  pc 0x00007fed37fc7a0d fp 0x00007fed3575fd10 dart::bin::Snapshot::TryReadAppSnapshot(char const*, bool, bool)+0x28d
  pc 0x00007fed37fcb296 fp 0x00007fed3575fdb0 dart+0x1dcf296
  pc 0x00007fed37fc8cc2 fp 0x00007fed3575fe30 dart::bin::DartDevIsolate::DartDevRunner::RunCallback(unsigned long)+0x62
  pc 0x00007fed3810ca82 fp 0x00007fed3575fe70 dart+0x1f10a82
-- End of DumpStackTrace
Aborted (core dumped)

我已经将所有内容添加到path中,就像它在dart和flutter文档中提到的那样,并按照确切的步骤一一执行。

fhg3lkii

fhg3lkii1#

好吧,我在这个问题上花了点功夫,找到了一个可能不值得的解决方案。
正如dart-lang#46749所指出的,这实际上是由WSL中mmap()的bug引起的,并且它是由this commit触发的,或者具体地说,changes in this file。正如提交消息所建议的,此更改是对分支预测的优化,因此,恢复它应该是安全的。常规的方法是重新构建dart SDK,删除runtime/bin/file_linux.cc中的hint = reinterpret_cast<void*>(&Dart_Initialize);行(未经验证)。当然,这不是人们愿意做的事情,我也是。相反,我试图修补dart-sdk/bin/dart的二进制文件,以删除执行该赋值的指令。
有效的操作非常简单:将特定位置的mov更改为nop。由于该指令的确切地址在不同的构建中可能会改变,因此可能必须遵循以下步骤来查找该地址:
随着命令

readelf -sC --wide dart-sdk/bin/dart | grep File::Map

你会得到类似于

11681: 000000000221cee0   138 FUNC    GLOBAL DEFAULT   14 dart::bin::File::Map(dart::bin::File::MapType, long, long, void*)

其中000000000221cee0是问题函数的地址。
您可以使用

objdump -dC --show-raw-insn --disassemble="dart::bin::File::Map(dart::bin::File::MapType, long, long, void*)" dart-sdk/bin/dart

并且要移除的指令是

48 8b 04 c8             mov    (%rax,%rcx,8),%rax

lea280df80之后。或者,您可以跳过查看程序集,因为它与实际修补无关。
最后我们来看看关键的操作,也是最难的操作:编辑二进制文件以删除该指令。这比人们想象的要复杂得多,我不知道一个好的方法来做这件事。使用little-endian字节顺序,十六进制序列在十六进制编辑器查看elf时会发生扭曲,因此很难手工修改二进制。我找到了工具radare2来做这件事。
首先,在写模式下启动radare2

radare2 -w dart-sdk/bin/dart

然后会弹出一个交互式提示。输入aaaa并等待分析完成。
之后,输入s 0x221cee0跳转到有问题的函数,其中0x221cee0是之前readelf找到的地址。
输入Vpc,将显示该函数的程序集。用箭头键将光标移动到lea rax, [0x0280df80]后的mov指令。在我的例子中,它是0x0221cf02
woa键,系统将提示您键入指令以替换原始mov指令。输入nop,以便跳过此指令。
Esc并输入q退出。好了
由于此操作修改了二进制文件,因此您应该事先备份原始的二进制文件。
这种方法看起来确实过于复杂,但主要的困难只是在替换该指令的步骤中。也许radare2中的所有魔力都可以在一个命令中完成,但现在发现这个解决方案后我已经没有精力去寻找了。

相关问题