Your question originally didn't state whether this is for 64-bit Cygwin G++/MSVC++ or 32-bit. There is a subtle difference when it comes to name decorations.
x86 (32-bit Windows PE) solution with OBJCOPY
I'll assume you had a resource file called Resources_0.png
. You can generate a 32-bit Windows PE object file with:
objcopy --prefix-symbol=_ --input-target binary --output-target \
pe-i386 --binary-architecture i386 Resources_0.png Resources_0.obj
The --prefix-symbol=_
appends an additional underscore (_
) to each label. Name decorating with an additional _
is standard for Win32/PE external object. The resulting file would have produced an object with these labels:
__binary_Resources_0_png_start
__binary_Resources_0_png_end
__binary_Resources_0_png_size
MSVC++ and Cygwin G++ targeting 32-bit executables can reference these labels as:
extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];
x86-64 (64-bit Windows PE) solution with OBJCOPY
You can generate a 64-bit Windows PE object file with:
objcopy --input-target binary --output-target pe-x86-64 --binary-architecture i386 \
Resources_0.png Resources_0.obj
This is similar to the 32-bit however we no longer add an additional underscore (_
) before each label. That is because in 64-bit PE code the names aren't decorated with an additional underscore.
The resulting file would have produced an object with these labels:
_binary_Resources_0_png_start
_binary_Resources_0_png_end
_binary_Resources_0_png_size
MSVC++ and Cygwin G++ targeting 64-bit Windows PE executables can reference these labels the exact same was as the 32-bit Windows PE version above:
extern "C" uint8_t _binary_Resources_0_png_start[];
extern "C" uint8_t _binary_Resources_0_png_end[];
extern "C" uint8_t _binary_Resources_0_png_size[];
Special note: When compiling with MSVC++ as 64-bit code you may end up with this linking error when using the size
label:
absolute symbol '_binary_Resources_0_png_size' used as target of REL32 relocation in section 4
With 64-bit code you can avoid this by computing the size in your C++ code by using the difference between the start
and end
labels like this:
size_t binary_Resources_0_png_size = _binary_Resources_0_png_end - \
_binary_Resources_0_png_start;
Other Observations
Even if using G++/GCC this is bad form:
extern uint8_t data[] asm("_binary_Resources_0_png_start");
extern uint8_t size[] asm("_binary_Resources_0_png_size");
extern uint8_t end[] asm("_binary_Resources_0_png_end");
There is little need for doing this and it is less portable. See the solutions above that don't use asm
directive on variables for G++ code.
The question is tagged both C and C++ and the question contains code with extern "C"
. The answer above assumes you are compiling .cpp
files with G++/MSVC++. If compiling .c
files with GCC/MSVC then change extern "C"
to extern
If you want to generate Windows PE objects with OBJCOPY where the data is placed in the read-only .rdata
section rather than .data
section, you can add this option to the OBJCOPY commands above:
--rename-section .data=.rdata,CONTENTS,ALLOC,LOAD,READONLY,DATA
I discuss this option in this Stackoverflow answer. The difference being that in Windows PE the read-only section is usually called .rdata
where as with ELF objects it is .rodata
_data
,_size
... would help. you could get rid of theasm
part then. I did the same thing, but created asm files from binary instead of usingobjcopy
, that gives control on the symbol names. – Faubionextern "C"
to each external variable. – Hobson