flipper-io / flipper

Flipper is a development platform that can be controlled from any programming language.
https://www.flipper.io/
Apache License 2.0
70 stars 15 forks source link

Dwarf parser #107

Closed nicholastmosher closed 6 years ago

nicholastmosher commented 6 years ago

Ready for Review

This is a tracking PR for adding dwarf parsing to the flipper console. With this, we'll be able to read debugging symbols from binaries compiled with -g in order to rebuild the function signatures of functions annnotated with LF_FUNC. Using these signatures, we'll then be able to auto generate high level language bindings with FMR-invoking implementations.

Testing

To test the changes in this PR, fetch and check out this branch, then use cargo run to read the already committed elf_section_test binary.

git fetch upstream
git checkout upstream/feature/fdwarf
cargo run -- binding dwarf src/bindings/test_resources/elf_section_test

Needs improvement/help

Currently, the dwarf parsing works perfectly on the elf_section_test file. However, I added a new dwarf_parse_test file with some more tricky function signatures to really check that it works in a wide range of scenarios and I started getting unexpected behavior. Specifically, the DwarfAttributeMissingError is triggering when I'm not expecting. The location it's being raised at is parse_parameter. I'll be looking into this more shortly.

Investigating with dwarfdump

One of gimli's example projects is a very useful dwarfdump utility, you can use it like this:

git clone git@github.com:gimli-rs/gimli.git ~/gimli

# Perhaps put this function into a bash alias file
dwarfdump() { cargo run --manifest-path=~/gimli/Cargo.toml --example dwarfdump -- $@ }

Then just do dwarfdump src/bindings/test_resources/dwarf_parse_test.

nicholastmosher commented 6 years ago

I found out what the problem was. When a subprogram has a void return type, it simply does not define a DW_AT_type for that subprogram. However, the parser was expecting to find a type for every subprogram and thus failed. I've fixed it by making the field for return type of a subprogram an Option rather than a required field.

As a side effect of debugging this, I've added more comprehensive error reporting in the parser, so it should be easier to detect problems of this nature in the future.

Tests are still a work in progress.

nicholastmosher commented 6 years ago

I've added in support for typedefs, which seems to be the last big thing that was blocking this from being ready for general use. The entry point to the parser is the parse_dwarf function, and simply returns a Vec<Subprogram> on successful parsing. The parse::test mod shows the expected data that should come out of the dwarf_parse_test binary. To run this locally, checkout the branch and use cargo run pointed at the binary.

git fetch upstream
git checkout fdwarf upstream/fdwarf
cd console
cargo run -- binding dwarf src/bindings/test_resources/dwarf_parse_test

This currently won't give any output because parse_dwarf just returns the values, it doesn't print anything. To see the parsing in action, add a line like this near the end of the parse_dwarf function:

println!("Got subprograms: {:?}", resolved_subprograms);