How to include data object files (images, etc.) in program and access the symbols?

后端 未结 4 1598
耶瑟儿~
耶瑟儿~ 2020-12-02 00:12

I\'ve turned a couple of resource files into .obj files using objcopy and i link them with my programs source code. I can very well access the symbols inside th

4条回答
  •  醉酒成梦
    2020-12-02 00:50

    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

提交回复
热议问题