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

[Feature Request] Ability to specify load addresses (generate ProgramHeaders, Segments) #107

Open
kitlith opened this issue Dec 7, 2019 · 9 comments

Comments

@kitlith
Copy link
Contributor

kitlith commented Dec 7, 2019

For my usecase, I'm wrapping a memory dump in an ELF and bundling it with available symbols so that I can easilly open it up in something like ghidra. Unfortunately, what is currently output is a partially linked file, which I can pass through a linker with a linker script that does almost nothing, but is an extra step that I would prefer to remove.

This would require (at minimum!) the ability to set the location of sections and ability to set the address of the entrypoint.

@m4b
Copy link
Owner

m4b commented Dec 8, 2019

Yea, so I started work on a pure rust in-memory minimal linker a few times, but I lost interest/got distracted because it gets extremely complicated very quickly, along with lots of undocumented issues, and other tedious things. (Although this was before faerie and goblin writer structs, so it might be easier now.)

I still think it would be very cool; but adding even "minor" linker requires one to effectively create a full linker, in my experience.

This might be somewhat easier now that goblin has all the writer values + faerie does a lot of the heavy lifting with symbol collection and other boring things.

I think it would probably be feasible to add a fully linked step, but i suspect it will be a pretty invasive PR? and a non-trivial amount of work. Or maybe not? I'm not sure.

But it would be quite cool to do this:

    let mut obj = ArtifactBuilder::new(target)
        .name(args.filename.clone())
        .link(SharedLibrary) // or .link(PieExecutable) or .link(StaticExecutable)
        .finish();

@kitlith
Copy link
Contributor Author

kitlith commented Dec 8, 2019

well, at least in my case, I don't need to do any actual linking. i just need a way to specify the memory location of section(s) and specify an entry point. but, it is definitely better to design for the future on this point, and I'm not familiar enough with the field to come up with a good design.

@m4b
Copy link
Owner

m4b commented Dec 8, 2019

i see; so if I understand correctly, you effectively want to specify the entry point field in the object file? i think that's somewhat unusual, since object files don't really have an entry point, since they aren't relocated and linked.

For section locations, they should always start at 0x40 and then proceed upwards depending on size (and probably alignment, i think)

@kitlith
Copy link
Contributor Author

kitlith commented Dec 8, 2019

essentially, i have a pre-linked blob that loads at a static address. what i want is an executable, not an object file per-se. The difference between the two files I uploaded in my PR appears to just be in the header(s) and a bit of padding.

@m4b
Copy link
Owner

m4b commented Dec 8, 2019

got it; so almost a sort of passthrough linker, in that it takes the artifact info, and without relocating, just simply emits an executable with some given entry point.

this seems like a somewhat niche usecase, but it would also be first start for writing out a linked binary, so subsequent work in that area, if it ever happens, would probably be able to re-use it?

i wonder if it's reasonable for you to just emit the bytes instead of into the file, and then alter the header to be an exe, along with some other things. if it really is just passed through, it might be as simple as writing the Elf header to have your entry point + make the binary type executable...?

@m4b
Copy link
Owner

m4b commented Dec 8, 2019

E.g., something like:

let mut obj = artifact.to_bytes::<Elf>()?;
let mut header = obj.pread::<Header>(0);
header.e_type = header::ET_EXEC;
header.e_entry = 0xdeadbeef;
obj.pwrite(header, 0)?;

@kitlith
Copy link
Contributor Author

kitlith commented Dec 8, 2019

that might be reasonable for me to do. I'll also need to assign the section an address, but it shouldn't be too difficult to do on top of that.

@kitlith
Copy link
Contributor Author

kitlith commented Dec 8, 2019

Ah, a program header is also missing. I bet that's (part of?) the """extra padding""" i mentioned. It specifies the load address of the section, etc. I could... append this to the end of the file when doing it manually? i kinda forgot that elf headers can just be placed wherever you like. hmmm...

@kitlith
Copy link
Contributor Author

kitlith commented Dec 8, 2019

I have a working incantation: https://gist.github.com/kitlith/a26a1021c268b34bef60d57cfc6cc19f#file-wasm_lib-rs-L50-L83

Nevertheless, I think it would be nice if we could instruct faerie to generate program headers of some sort.

EDIT: yeah i'm pretty sure that missing ProgramHeaders are my main issue, rather than relocatable vs executable and other stuff. ProgramHeaders are optional in relocatables, which means they are still allowed to occur. I'm having some ideas here, maybe an optional artifact.locate() to parallel artifact.declare() and artifact.define()?

EDIT again: for mach-o, this would require generating segments and specifying their vmaddr :/

@kitlith kitlith changed the title [Feature Request] Ability to output a fully linked executable that doesn't need a linking step [Feature Request] Ability to specify load addresses (generate ProgramHeaders, etc.) Dec 8, 2019
@kitlith kitlith changed the title [Feature Request] Ability to specify load addresses (generate ProgramHeaders, etc.) [Feature Request] Ability to specify load addresses (generate ProgramHeaders, Segments) Dec 8, 2019
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

2 participants