incbin "file.bin", -16, 16 # how to include only the last e.g. 16 bytes of a file, when the file has a different size in each compilation

45 views Asked by At

How include to build object file the last bytes of binary file The as contain directive incbin, but i don know how select range relative to the end of file

I know how to extract a range of bytes into a new file and use it in a Makefile. This works, but the sizes of these files are in terabytes

1

There are 1 answers

2
ndim On

This looks to be one of the cases where the programmer not only needs to know their programming language, but also their build system.

So you let the build system write the .incbin directive with the proper numbers.

If the binary file is called bar.bin and I want that as a global symbol bar, I would do something along these lines (presuming a make based build system):

/* foo.S */
        .global bar
        .type   bar, @object
bar:
        .include "bar-incbin.S"
        .size   bar, . - bar
# Makefile
STAT = stat

foo.o: foo.S bar-incbin.S bar.bin
        $(AS) -o $@ -c $<

bar-incbin.S: bar.bin
        set -ex; \
        fsize="$$($(STAT) -c "$%s" $<)"; \
        count="16"; \
        if test "$$count" -gt "$$fsize"; then \
          printf "Error: File $< is too small (smaller than %u)\n" "$$count"; \
          rm -f "$@"; \
          exit 2; \
        fi; \
        skip="$$(expr "$$fsize" - "$$count")"; \
        printf "/* $@ autogenerated from $< */\n" > $@; \
        printf ".incbin \"%s\",%u,%u\n" "$@" "$$skip" "$$count" >> $@

So if bar.bin is 256 bytes, this will generate a file

/* bar-incbin.S autogenerated from bar.bin */
.incbin "bar-incbin.S",240,16

which will then be included into foo.S when foo.S is being assembled.

There are other ways do to this as well. E.g.

# Makefile
STAT = stat

OBJS += bar.o

%.S: %.bin
        set -ex; \
        fsize="$$($(STAT) -c "$%s" $<)"; \
        count="16"; \
        if test "$$count" -gt "$$fsize"; then \
          printf "Error: File $< is too small (smaller than %u)\n" "$$count"; \
          rm -f "$@"; \
          exit 2; \
        fi; \
        skip="$$(expr "$$fsize" - "$$count")"; \
        printf "/* $@ autogenerated from $< */\n" > $@; \
        printf "\t.balign\t$$count" >> $@; \
        printf "\t.global\t$*" >> $@; \
        printf "\t.type\t$*, @object" >> $@; \
        printf "$*:" >> $@; \
        printf "\t.incbin\t\"%s\",%u,%u\n" "$@" "$$skip" "$$count" >> $@; \
        printf "\t.size\t$*, . - $*" >> $@

So if bar.bin is 1TiB = 1099511627776 in size, this will generate a bar.S to be assembled which looks like

/* bar.S autogenerated from bar.bin */
        .balign 16
        .global bar
        .type   bar, @object
bar:
        .incbin "bar.bin",1099511627760,16
        .size   bar, . - bar

which will then be assembled into an object file bar.o which contains the 16 byte aligned symbol bar of size 16 which contains the last 16 bytes of the bar.bin file.