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

build-exe: ability to output raw binary or hex format rather than ELF #2826

Open
andrewrk opened this issue Jul 5, 2019 · 11 comments
Open
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Jul 5, 2019

Sometimes it is desirable to get the raw machine code out of an ELF and use that. This example depends on objcopy to do that, but it should be doable with only zig:

https://github.com/andrewrk/clashos/blob/3f786d4294c71f909b1ecaf3c8d0e247b90c5c86/build.zig#L32-L37

I think this would probably be more options to --emit. Current options are:

  • llvm-ir
  • bin (ELF or PE)
  • asm

Unfortunately, bin is a bit ambiguous here. I think it would be OK to add:

  • ihex (equivalent to objcopy -O ihex)
  • raw (eqivalent to objcopy -O binary)

We could leave bin the same, or potentially try to come up with a less ambiguous name.

As for how to implement it - LLVM in theory should have a way to specify this, since it's actually less work to generate raw machine code than to wrap it in an ELF. But worst case scenario, zig could do the processing after the fact.

If we end up having to implement intel hex format, it could be written in zig itself, the same way that zig fmt and the new translate-c work.

@andrewrk andrewrk added enhancement Solving this issue will likely involve adding new logic or components to the codebase. contributor friendly This issue is limited in scope and/or knowledge of Zig internals. stage1 The process of building from source via WebAssembly and the C backend. labels Jul 5, 2019
@andrewrk andrewrk added this to the 0.6.0 milestone Jul 5, 2019
@MasterQ32
Copy link
Contributor

I really like the idea of zig to directly output raw oder intel hex formats!

What would also be favourable: To output PE under linux and ELF under windows to cross-compile for different platforms.

This could finally allow to have a build system that doesn't suck at "one project, multiple platforms" without a hassle.

@zimmi
Copy link
Contributor

zimmi commented Jul 6, 2019

What would also be favourable: To output PE under linux and ELF under windows to cross-compile for different platforms.

That's already possible, see here.
I just tried running this build.zig on my linux machine and it produced a .exe for windows:

const Builder = @import("std").build.Builder;
const builtin = @import("builtin");

pub fn build(b: *Builder) void {
    const mode = b.standardReleaseOptions();
    const exe = b.addExecutable("my_exe", "src/main.zig");
    exe.setBuildMode(mode);
    exe.setTarget(
        builtin.Arch.x86_64,
        builtin.Os.windows,
        builtin.Abi.msvc,
    );
    exe.install();
}

@suirad
Copy link
Contributor

suirad commented Nov 27, 2019

This would also be desirable to be able to write shellcode with zig.

@mlarouche
Copy link
Sponsor Contributor

I will look into that issue soon

mlarouche added a commit to mlarouche/zig that referenced this issue Jan 26, 2020
* Add --custom-ext to stage1 build-exe, allow to customize the exectuable extension for --emit bin or --emit raw
* Add setEmit to Zig build system
* Add addExecutableCustomExtension to Zig build system to customize the executable extension, useful for emit raw
* Implement emit_raw in stage1/stage2 Zig that does a similar job to llvm-objcopy
* Add custom_extension and emit_raw / no_emit_raw to cache digest

Part of ziglang#2826
mlarouche added a commit to mlarouche/zig that referenced this issue Feb 1, 2020
…m-objcopy. To use it, do

```zig
exe.installRaw("kernel.bin");
```

where exe is a LibExeObjStep

Part of ziglang#2826
mlarouche added a commit to mlarouche/zig that referenced this issue Feb 1, 2020
…m-objcopy. To use it, do 'exe.installRaw("kernel.bin");' where exe is a LibExeObjStep

Part of ziglang#2826
@daurnimator
Copy link
Collaborator

this would probably be more options to --emit

How should this co-exist with #2279 (comment) ?

--emit is deprecated;

andrewrk pushed a commit that referenced this issue Feb 3, 2020
…m-objcopy. To use it, do 'exe.installRaw("kernel.bin");' where exe is a LibExeObjStep

Part of #2826
@markfirmware
Copy link
Contributor

I am using installRaw and then running a zig program to convert to intel hex (for the microbit.)

The build function does "addSystemCommand("zig", "build", "makehex.zig") which works, but I'd like to add the makehex function directly as a build step. Is there a builder function that can add a zero parameter/return !void function?

https://github.com/markfirmware/zig-bare-metal-microbit/blob/master/makehex.zig
https://github.com/markfirmware/zig-bare-metal-microbit/blob/master/build.zig

@daurnimator
Copy link
Collaborator

See also: COFF

@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Oct 14, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@auwi-nordic
Copy link

I think it would be very useful if this could be implemented in a way where you could write your own custom code to generate output files. In our environment we need the "verilog" output of objcopy. Maybe that's too niche for Zig.. but only raw binary and intel hex is a bit artificially limited as well.

So somehow you would provide a function that takes a pointer to parsed ELF data, and an output file, and you'd be responsible for writing what you want to that file.

Another useful output for us is symbol tables (--sym output of objdump).. with this kind of general purpose tool, we could perhaps write symbol table in a format that's more useful for us, rather than trying to parse the output of objdump

@LemonBoy
Copy link
Contributor

You can already do that, the raw output mode is entirely implemented in "user space" and not baked into the compiler.

@auwi-nordic
Copy link

@LemonBoy You're talking about this right? https://github.com/ziglang/zig/blob/master/lib/std/build/emit_raw.zig

I saw that, so what I was thinking is making it more easy to define a custom output step, where the ELF related stuff is already handled for you.

And the other side of making it easier would be documentation.. but then I guess that's a big TODO for the whole build system anyway

Right now I guess you can't even reuse the "BinaryElfOutput" related stuff, since it's not "pub" right? And you wouldn't know to look for it in emit_raw.zig anyway. But that would have been useful

If you have an interface that gives you an ELF file reader rather than a path, you could potentially have an optimization where the ELF file is only read to memory once for all output steps

@zigazeljko
Copy link
Contributor

LLVM in theory should have a way to specify this

In fact, it does. You can pass --oformat=binary to LLD and it will output raw binary data (equivalent to objcopy -O binary).

@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
ehaas added a commit to ehaas/zig that referenced this issue Aug 27, 2021
This allows writing HEX files with `exe.installRaw`, where `exe` is a
`LibExeObjStep`. A HEX file will be written if the file extension is `.hex`
or `.ihex`, otherwise a binfile will be written. The output format can be
explicitly chosen with `exe.installRawWithFormat("filename", .hex);`
(or `.bin`)

Part of ziglang#2826

Co-authored-by: Akbar Dhanaliwala <akbar.dhanaliwala@gmail.com>
ehaas added a commit to ehaas/zig that referenced this issue Aug 28, 2021
This allows writing HEX files with `exe.installRaw`, where `exe` is a
`LibExeObjStep`. A HEX file will be written if the file extension is `.hex`
or `.ihex`, otherwise a binfile will be written. The output format can be
explicitly chosen with `exe.installRawWithFormat("filename", .hex);`
(or `.bin`)

Part of ziglang#2826

Co-authored-by: Akbar Dhanaliwala <akbar.dhanaliwala@gmail.com>
ehaas added a commit to ehaas/zig that referenced this issue Aug 29, 2021
This allows writing HEX files with `exe.installRaw`, where `exe` is a
`LibExeObjStep`. A HEX file will be written if the file extension is `.hex`
or `.ihex`, otherwise a binfile will be written. The output format can be
explicitly chosen with `exe.installRawWithFormat("filename", .hex);`
(or `.bin`)

Part of ziglang#2826

Co-authored-by: Akbar Dhanaliwala <akbar.dhanaliwala@gmail.com>
ehaas added a commit to ehaas/zig that referenced this issue Sep 1, 2021
This allows writing HEX files with `exe.installRaw`, where `exe` is a
`LibExeObjStep`. A HEX file will be written if the file extension is `.hex`
or `.ihex`, otherwise a binfile will be written. The output format can be
explicitly chosen with `exe.installRawWithFormat("filename", .hex);`
(or `.bin`)

Part of ziglang#2826

Co-authored-by: Akbar Dhanaliwala <akbar.dhanaliwala@gmail.com>
@Vexu Vexu removed the stage1 The process of building from source via WebAssembly and the C backend. label Dec 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. enhancement Solving this issue will likely involve adding new logic or components to the codebase.
Projects
None yet
Development

No branches or pull requests