Skip to content

Instantly share code, notes, and snippets.

@mmozeiko
Last active December 7, 2023 04:10
Show Gist options
  • Star 53 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save mmozeiko/ed9655cf50341553d282 to your computer and use it in GitHub Desktop.
Save mmozeiko/ed9655cf50341553d282 to your computer and use it in GitHub Desktop.
Include binary file with gcc/clang
#include <stdio.h>
#define STR2(x) #x
#define STR(x) STR2(x)
#ifdef _WIN32
#define INCBIN_SECTION ".rdata, \"dr\""
#else
#define INCBIN_SECTION ".rodata"
#endif
// this aligns start address to 16 and terminates byte array with explict 0
// which is not really needed, feel free to change it to whatever you want/need
#define INCBIN(name, file) \
__asm__(".section " INCBIN_SECTION "\n" \
".global incbin_" STR(name) "_start\n" \
".balign 16\n" \
"incbin_" STR(name) "_start:\n" \
".incbin \"" file "\"\n" \
\
".global incbin_" STR(name) "_end\n" \
".balign 1\n" \
"incbin_" STR(name) "_end:\n" \
".byte 0\n" \
); \
extern __attribute__((aligned(16))) const char incbin_ ## name ## _start[]; \
extern const char incbin_ ## name ## _end[]
INCBIN(foobar, "binary.bin");
int main()
{
printf("start = %p\n", &incbin_foobar_start);
printf("end = %p\n", &incbin_foobar_end);
printf("size = %zu\n", (char*)&incbin_foobar_end - (char*)&incbin_foobar_start);
printf("first byte = 0x%02hhx\n", incbin_foobar_start[0]);
}
@Ionizing
Copy link

Ionizing commented Mar 24, 2023

This solution works fine on both Linux and Windows, but failed on macOS. I modified a bit and make it run on macOS (x86).

  • Support macOS (x86)
  • Add optional prefix for variable name
#include <stdio.h>

#define STR2(x) #x
#define STR(x) STR2(x)

#ifdef __APPLE__
#define USTR(x) "_" STR(x)
#else
#define USTR(x) STR(x)
#endif

#ifdef _WIN32
#define INCBIN_SECTION ".rdata, \"dr\""
#elif defined __APPLE__
#define INCBIN_SECTION "__TEXT,__const"
#else
#define INCBIN_SECTION ".rodata"
#endif

// this aligns start address to 16 and terminates byte array with explict 0
// which is not really needed, feel free to change it to whatever you want/need
#define INCBIN(prefix, name, file) \
    __asm__(".section " INCBIN_SECTION "\n" \
            ".global " USTR(prefix) "_" STR(name) "_start\n" \
            ".balign 16\n" \
            USTR(prefix) "_" STR(name) "_start:\n" \
            ".incbin \"" file "\"\n" \
            \
            ".global " STR(prefix) "_" STR(name) "_end\n" \
            ".balign 1\n" \
            USTR(prefix) "_" STR(name) "_end:\n" \
            ".byte 0\n" \
    ); \
    extern __attribute__((aligned(16))) const char prefix ## _ ## name ## _start[]; \
    extern                              const char prefix ## _ ## name ## _end[];

INCBIN(incbin, foobar, "binary.bin");

int main()
{
    printf("start = %p\n", &incbin_foobar_start);
    printf("end = %p\n", &incbin_foobar_end);
    printf("size = %zu\n", (char*)&incbin_foobar_end - (char*)&incbin_foobar_start);
    printf("first byte = 0x%02hhx\n", incbin_foobar_start[0]);
}

The code above can also be found in my fork.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment