Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One step setup #43

Closed
japaric opened this issue Feb 21, 2018 · 59 comments
Closed

One step setup #43

japaric opened this issue Feb 21, 2018 · 59 comments

Comments

@japaric
Copy link
Member

japaric commented Feb 21, 2018

Embedded development involves cross compilation and remote debugging; the Rust toolchain doesn't
provide all the tools so you have to install external ones like: a cross linker (e.g.
arm-none-eabi-ld), a cross debugger (e.g. arm-none-eabi-gdb), some tool to communicate with the
remote target (e.g. OpenOCD), etc.

It would be great if the user didn't have to figure out where to get all those tools and install
them manually.

There are a few upcoming changes that might affect this situation.

lld is a multi-arch linker and it can be used to link ARM Cortex-M binaries so once this is in
place user won't need to install arm-none-eabi-ld.

I don't think lld supports any of the other embedded targets (MSP430, AVR or RISCV) though

lldb is a multi-arch debugger. I personally could never get it to work with OpenOCD; I never found
an equivalent to the monitor and load commands which are used to flash the binary into the
remote target. lldb can debug ARM Cortex-M programs just fine; I have used it debug a emulated ARM
Cortex-M microcontroller (QEMU).

Maybe someone had more luck with it and can share their experience?


One way to address this setup problem could be to provide a installer (script) like
https://rustup.rs/ does but for each target architecture.

cc @jcsoo

@whitequark
Copy link

I never found an equivalent to the monitor and load commands which are used to flash the binary into the remote target.

The monitor command is process plugin packet monitor in lldb, and I'm afraid it's rather user unfriendly:

(lldb) process plugin packet monitor help
  packet: qRcmd,68656c70
response: O54686520666f6c6c6f77696e67206d6f6e69746f7220636f6d6d616e64732061726520737570706f727465643a0a

The flash functionality of the gdb stub is not supported.

IMO, it's a good idea to extend lldb to handle these use cases instead of giving up on it.

@jcsoo
Copy link

jcsoo commented Feb 21, 2018

I haven't had a chance to try LLD / LLDB yet - for now, do you have to build LLVM from scratch to install them? What version should we be using to be close to what Rust is using? Or can we get them by doing a full Rust build?

Bobbin-CLI (https://github.com/bobbin-rs/bobbin-cli/) currently knows about many debuggers and flash loaders, and the documentation currently has pointers to download sites as well as some documentation about how to build and install them: https://github.com/bobbin-rs/bobbin-cli/blob/master/FIRMWARE.md

There's also a "bobbin check" command that scans for all tools that it knows about and displays version information:

mbp15:~ jcsoo$ bobbin check
    Bobbin 0.8.0
      Rust 1.25.0-nightly (27a046e93 2018-02-18)
     Cargo 0.26.0-nightly (1d6dfea44 2018-01-26)
     Xargo 0.3.10
       GCC 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]
   OpenOCD 0.10.0+dev-g7c2dc13 (2017-02-12-10:20)
     JLink V6.19e (Compiled Sep  1 2017 18:27:51)
     Bossa 1.7.0
    Teensy 2.1
  dfu-util 0.9

This could conceivably be extended to check for outdated versions and to add direct documentation links. Bobbin-CLI also has a database of USB Vendor / Product IDs that could be used
to auto-detect devices with missing tools and point users to documentation and download links.

I've considered adding rustup style functionality but I don't think it's practical because of the third-party nature of these tools. I think the effort is better spent in building rust-native tools and/or building support directly into Bobbin-CLI. For instance, Teensy is a simple USB HID protocol, dfu-util is a reasonably straightforward USB protocol, and Bossa uses a serial protocol.

Bobbin-CLI also supports dumping files onto USB MSD volumes, which covers many ST-Link and DAPLink debuggers, and it might not be too difficult to teach it enough of the GDB remote protocol to handle flashing to anything that exposes a GDB server (JLink, and Black Magic Probe). In the long run there is https://github.com/mbedmicro/FlashAlgo which is collecting flash algorithms for a wide variety of targets.

So, it could conceivably have native flash loading support for a fairly broad range of boards and debuggers, limiting the OpenOCD dependency to people that need remote debugging or need to support devices that aren't covered.

@dvc94ch
Copy link
Member

dvc94ch commented Feb 22, 2018

So is there interest in making an openocd crate so that it can be installed via cargo? I think this would be a requirement for useful cargo flash and cargo debug commands.

@whitequark
Copy link

Repackaging completely unrelated C applications in cargo seems wrong. The gcc crate doesn't package gcc...

@hannobraun
Copy link
Member

@jcsoo

I think the effort is better spent in building rust-native tools and/or building support directly into Bobbin-CLI. For instance, Teensy is a simple USB HID protocol, dfu-util is a reasonably straightforward USB protocol, and Bossa uses a serial protocol.

A few years ago, I built a simple tool to replace Bossa for my own use, to upload to the SAM3X8E. Here: https://github.com/hannobraun/embedded/tree/master/uploader

I don't know how much is missing to make it useful, but I recall successfully using it to upload my program at the time. Maybe it can serve as a starting point or reference for your own efforts.

@dvc94ch
Copy link
Member

dvc94ch commented Feb 22, 2018

@whitequark gcc isn't essential to the toolchain, and would require a dozen different crates for each architecture. Relying on distro package managers can be an option for Linux/established computer architectures. If we want a seamless experience for non-linux and archs like riscv, what do you suggest as an alternative? Rewriting openocd in rust is probably not a realistic goal till September

@whitequark
Copy link

whitequark commented Feb 22, 2018

@dvc94ch If you want a seamless experience? Rely on system package managers for Linux and OS X, and provide prebuilt Windows installers.

Even if you did package openocd as a crate, it depends on, at least, MinGW, MSYS and libusb1 to build on Windows, and these dependencies ensure that it's not going to be installable as simple as cargo install openocd. That's forgetting about any adapters more complex than FTDI ones...

@thejpster
Copy link
Contributor

thejpster commented Feb 22, 2018 via email

@jcsoo
Copy link

jcsoo commented Feb 22, 2018

When Rust has LLD and LLDB integration, does anyone know whether Rust will build, ship, and install the standalone binaries also? And what about other utilities? objcopy will be needed to convert to hex format for many flash loaders, and I use objdump + size very often.

I would hate to do all this work and still need the user to install the full GCC or LLVM toolchain just to get access to those utilities.

Could they be packaged in a separate rustup rust-tools component?

@thejpster
Copy link
Contributor

thejpster commented Feb 22, 2018 via email

@whitequark
Copy link

They're from GNU Binutils, which is distinct to GCC and LLVM.

There are llvm-objdump and llvm-size since sometime late in 3.x cycle.

I'm OK with depending upon binutils as-is.

binutils are a really gross dependency to carry around. First, you get an entire second machine layer with its own independent bugs and deficiencies. There's no guarantee that the disassembler in binutils will know about all the same relocations as LLVM. (I've hit this.) Second, they're a pain in the ass to build on Windows as they require msys or cygwin.

@japaric
Copy link
Member Author

japaric commented Feb 22, 2018

When Rust has LLD and LLDB integration, does anyone know whether Rust will build, ship, and install the standalone binaries also?

That's what rust-lang/rust#48125 does. A LLD binary will be shipped with the Rust toolchain; it will be somewhere in $(rustc --print sysroot). There's some magic that will append the path to LLD to the PATH env variable when rustc invokes the linker so the user won't have to do anything to their environment.

I don't know what's the LLDB plan with respect to PATH.

@japaric
Copy link
Member Author

japaric commented Feb 22, 2018

There's a Rust tool that's basically a objdump re-implementation. Unfortunately I don't recall its name but, iirc, it's based on the Keystone Capstone (dis)assembler.

EDIT: Err, not Keystone; Capstone I think

@japaric
Copy link
Member Author

japaric commented Feb 22, 2018

There's a Rust tool that's basically a objdump re-implementation.

It's called cargo-sym but it doesn't seem like they are working on it anymore (no activity in the last 11 months).

@whitequark
Copy link

whitequark commented Feb 22, 2018

I really don't think we should use anything besides llvm-objdump if we want to support lesser-used architectures. That's just duplicating work and introducing more opportunity for obscure errors.

Ask me about that time I found out that OR1K assemblers in LLVM and binutils didn't match up, and then that LLVM and ld.bfd didn't agree on whether some DWARF relocation is absolute or relative...

@japaric
Copy link
Member Author

japaric commented Feb 22, 2018

I tested llvm-objdump locally and it worked fine; I had to pass -triple=thumbv7m-none-eabi to it to get the correct diassembly though. I also didn't see any demangling option but piping the output through c++filt did the trick. llvm-size worked without problems.

Given that lld is being added to the Rust toolchain I think we could push (submit an RFC) for shipping both llvm-size and llvm-objdump with the toolchain. That would eliminate the need for installing arm-none-eabi-binutils when targetting ARM Cortex-M and would do the same for the other targets once they get LLD support.

Once llvm-objdump and llvm-size are in place we could publish some thin wrappers as Cargo subcommands (e.g. cargo-objdump) that take care of passing -triple, demangling the output, specifying the full path to the binary, etc.

@jcsoo
Copy link

jcsoo commented Feb 22, 2018

Can we get llvm-objcopy included also? It's needed for generating .bin or .hex files from the ELF output. All of the flash loaders (Bossa, Teensy, dfu-util) as well as ST-Link and DAPLink on-board drag-and-drop require one of those two formats.

@whitequark
Copy link

While you're at it, also include:

  • llvm-nm
  • llvm-cxxfilt
  • llvm-cov

@thejpster
Copy link
Contributor

llvm-objdump and llvm-size since sometime late in 3.x cycle.

Oh, cool!

binutils are a really gross dependency to carry around

I totally agree that if there are LLVM equivalents then that's a much better approach, and an easier way to get all our architectures supported properly.

thin wrappers ... cargo-objdump

Oh man, that would really improve my workflow.

@japaric
Copy link
Member Author

japaric commented Feb 23, 2018

Based on the discussion so far I have created two work items:

Help wanted!

@dvc94ch
Copy link
Member

dvc94ch commented Mar 3, 2018

@therealprof had some success with lldb and stlink. [0]

monitor and load can probably be implemented as python scripts. If someone gets it working with openocd I can probably port lldb to riscv. According to [1] it doesn't seem too involved to get a basic working debugger running and could probably be implemented in a week or two. (gdb keeps segfaulting on me, so I'd be interested in trying a different debugger)

  • msp430 triple to LLDB
  • Describe msp430 registers in a python file
  • Fix DWARF parsing errors in LLDB
  • Added msp430 breakpoint opcode to LLDB
  • Implemented msp430 ABI
  • Hookup disassembler

[0] https://www.eggers-club.de/blog/2017/07/01/embedded-debugging-with-lldb-sure/
[1] https://llvm.org/devmtg/2016-03/Tutorials/LLDB-tutorial.pdf

@dvc94ch dvc94ch mentioned this issue Mar 3, 2018
7 tasks
@therealprof
Copy link
Contributor

therealprof commented Mar 3, 2018

@dvc94ch The "problem" with lldb is its funny interpretation of the "standard" gdbserver protocol. It'll pretty much only work reliably with it's own counter implementation lldb-server but none of the other available tools (e.g. OpenOCD or Blackmagic Probe) with the only notable exception being st-util from the STLink suite which works to a very basic extend.

I toyed around with lldb for a bit but the major problem I found was that lldb stuffs some important gdb commands into a NUL-terminated string instead of looking at and keeping their real size which means that you cannot put arbitrary binary data in them thus preventing a lot of stuff from working. Changing that seems to be a major effort, especially since lldb uses a rather antiquated development process with a more not so really open community.

@dvc94ch
Copy link
Member

dvc94ch commented Mar 3, 2018

lldb uses a rather antiquated development process with a more not so really open community

@therealprof mmh, are not the same people working on it that work on llvm? I got a small patch upstreamed, didn't seem that annoying. I guess it depends on who is actually in charge of the code you want to change? anyway that's a shame...

@therealprof
Copy link
Contributor

Ooh, actually there seems to be movement on the gdbserver protocol support front since I last checked http://lists.llvm.org/pipermail/lldb-dev/2018-January/013078.html .

@dvc94ch There's some overlap. But lldb is mostly handled by Apple and Google people.

@therealprof
Copy link
Contributor

Nice, things are starting to move. Google contributes vFlash command support to lldb just a few days back, however it has been reverted due to virtual/physical address confusion. Otherwise I'd had done a quick check of whether the OpenOCD situation has improved.

@pftbest
Copy link

pftbest commented Mar 3, 2018

@dvc94ch You mentioned msp430 in your comment, did you mean riscv?

@dvc94ch
Copy link
Member

dvc94ch commented Mar 3, 2018 via email

@whitequark
Copy link

Those don't work on Windows do they?

@andre-richter
Copy link
Member

andre-richter commented Apr 6, 2018 via email

@japaric
Copy link
Member Author

japaric commented Apr 6, 2018

Update on LLD: PR rust-embedded/cortex-m-rt#64 adds LLD support to cortex-m-rt. With that version you can build ARM Cortex-M programs without having to install arm-none-eabi-ld. Seems to work so far but will continue testing locally.

@thejpster
Copy link
Contributor

I use Docker for Windows on Windows 10 all day long. It spins up a Hyper-V VM running a very minimal Linux OS (just enough to run a Docker container) at boot-up and the rest is transparent.

@whitequark
Copy link

How about macOS?

@thejpster
Copy link
Contributor

thejpster commented Apr 6, 2018

It exists, but I haven't used it. Very similar idea I imagine.

https://docs.docker.com/docker-for-mac/

Edit to add:

Docker for Mac requires OS X El Capitan 10.11 or newer macOS release running on a 2010 or newer Mac, with Intel’s hardware support for MMU virtualization - https://docs.docker.com/docker-for-mac/install/#download-docker-for-mac

@therealprof
Copy link
Contributor

@whitequark What do you mean? Docker or run native?

@whitequark
Copy link

Do these prebuilt toolchains for macOS exist?

@therealprof
Copy link
Contributor

@whitequark Yes, there're pre-built toolchains. Anything specific you're looking for?

@andre-richter
Copy link
Member

andre-richter commented Apr 6, 2018 via email

@therealprof
Copy link
Contributor

@andre-richter Docker on Mac used to do Virtualbox VMs but now it runs stuff directly in a Hypervisor.

@therealprof
Copy link
Contributor

I haven't actually used docker for anything Rust so far. So far all bits ran just fine natively.

@andre-richter
Copy link
Member

andre-richter commented Apr 6, 2018 via email

@japaric
Copy link
Member Author

japaric commented Apr 9, 2018

Update: cortex-m-rt v0.4.0 has been released and it supports linking with LLD

@japaric
Copy link
Member Author

japaric commented Jul 4, 2018

Update from the dev-tools meeting regarding lldb: there has been ongoing work on improving Rust support in lldb and work there has been progressing nicely so they are now looking into shipping lldb as a rustup component.

@therealprof
Copy link
Contributor

Awesome. Now if the gdb server protocol wouldn't suck so much that solutions were actually compatible... Nothing we can fix if I had to hazard a guess.

@japaric
Copy link
Member Author

japaric commented Aug 2, 2018

Another update from dev-tools meeting regarding debuggers. It seems that the plan is to initially ship lldb on macOS and gdb on Linux as that would be faster to ship than to get lldb working perfectly everywhere and then ship that. Also this work is not part of the 2018 edition milestone so it's not high priority as other stuff but the initial shipping plan might get implemented in time for the 2018 edition.

Still I think we could request they ship a gdb compiled with --enable-targets=all and that would still be a net win on Linux as one could use the same rust-gdb for debugging native apps and embedded apps instead of having to install arm-none-eabi-gdb.

@therealprof
Copy link
Contributor

Weird. lldb runs perfectly on Linux, not sure what is missing here. I could understand if the notion was to use gdb on Linux because it provides more functionality but the same reasoning could be applied to ship gdb everywhere instead splitting between the two. 🤔

@dvc94ch
Copy link
Member

dvc94ch commented Aug 5, 2018

Just curious, now that https://reviews.llvm.org/D42145 has landed, has anyone tried using lldb for cortex-m recently?

@dvc94ch
Copy link
Member

dvc94ch commented Aug 10, 2018

Still I think we could request they ship a gdb compiled with --enable-targets=all and that would still be a net win on Linux as one could use the same rust-gdb for debugging native apps and embedded apps instead of having to install arm-none-eabi-gdb.

Is this happening?

@japaric
Copy link
Member Author

japaric commented Aug 10, 2018

Is this happening?

I'll ask.

What's the recommended gdb version for debugging RISCV binaries? HEAD, or does the latest stable release have good RISCV support?

@dvc94ch
Copy link
Member

dvc94ch commented Aug 10, 2018

binutils has been upstream for a while. Latest stable should be ok.

@jamesmunns
Copy link
Member

Closing this as part of the 2024 triage.

Today, it is possible to obtain binutils via rustup and using the cargo-binutils plugin, and much of the "one step" nature is handled by the compiler itself, or common tools like probe-rs run.

If you think this was closed incorrectly, please leave a comment and we can revisit this decision in the next weekly WG meeting on Matrix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests