3

I updated and uploaded some code on another computer that got wiped and didn't send the new code to my current computer, the updated code is still on the board but I don't have access to it. How do I get it back?

  • 6
    You have a couple of answers, but here's a piece of advice for going forward... protect yourself against code loss by learning how to use a VCS (Version Control System). This will allow you to keep all changes to your software on both your local computer as well as a remote system which stores it. Nowadays, I use git, but there are several. Github is a free online git storage facility. So you do some code, "commit" your changes, and then "push" them up to Github. You can then pull your code down to any computer with git on it thereafter. – stevieb Sep 18 at 20:22
  • You likely can't recover the source code, but if you had some important logic that you don't want to rewrite from scratch, it's very likely you can dump out the assembly and reconstruct that into C pretty easily (although manually). – Martin Sep 19 at 11:04
  • 1
    Isn't the code in one of your backups, or your version control system? – Mawg Sep 19 at 11:58
17

The short answer: You don't.

With enough know-how, you could probably extract the executable binary from the Arduino, but the source code is not installed on the device. You would need to run a decompiler on the binary. (Or read the machine code directly.) The output of a decompiler is usually pretty ugly however, and will look quite different from the original source-code. It won't have meaningful variable names, class names, or function names, and the code structure will likely be a little different than the original source code.

EDIT:

As mckenzm pointed out in his answer, you could download the binary image from your Arduino, and then copy it onto another Arduino, but all that would let you do is to make an exact copy of the program. You wouldn't be able to modify it at all.

8

You never can get the actual code back ... by reading the flash you might be able to get the executable/runtime code, but this doesn't look at all similar as your code, although it's functionally the same.

For example, all function names, all variable names will be just numbers (or non recognizable names), and all C statements are converted in machine language instructions, probably so many, you will need much knowledge to find out which instructions belong to which (original) C statements.

7
  1. You read the contents of flash and save it to a file. It can then be re-flashed if your need is not to edit, but duplicate.

    • This reads all flash, including the bootloader, and also PROGMEM data.
  2. Use avr-objdump (or similar) to disassemble the instructions.

    • Again, PROGMEM data is going to be interpreted as opcodes, and may not be valid opcodes.

    • You may want to dump the fuses as well, for redirected vectors and such.

  3. Use pattern analysis to recognise source patterns as compiled. Then iteratively compile and compare fragments.

This is harder than is looks, whilst most Arduino code is very simple, the libraries can be be wild and woolly. At least the hex file is human readable, but little endian.

It might be easier to "walk through" the assembly and perform a translation of the perceived behaviour. OK for 10 instructions, but harder for 16K of them.

You will also need the Atmel/Microchip *def.inc files for the MPU component enumerations so that you know your DDRB from you DDRC a good disasembler should know.

You can do this well enough for Blink, and recognise stack pointer initialization.

It is much easier without a bootloader, as booting should jump to main and main can start at 0 other than after the vectors.

Of course lock bits will ruin your day, and it may just be better for character to code it again.

  • Note that: 1. The Arduino IDE does not mess with the fuses nor lock bits. 2. Full-program optimization, which the IDE sets on by default, will make it near to impossible to find Arduino library functions by pattern-matching. Avr-libc is pre-compiled (with no LTO sections AFAICT), so it can be pattern-matched. 3. The boot loader will not be a problem: application code always starts at address 0, which is a jmp to __init. A few instructions through __init you find call main followed by jmp _exit. Thus, at least main is easy to find. Anything beyond will likely be a mess. – Edgar Bonet Sep 19 at 7:53
  • Good points. The IDE does set fuses for "burn bootloader". Especially for contributed cores and in particular for clock selection and bootloader operation. You always have the ICSP option. – mckenzm Sep 20 at 2:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.