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

后端 未结 4 1590
耶瑟儿~
耶瑟儿~ 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 01:04

    After working around and testing different things, i came back to my original approach (linking) and it worked like magic, here is the details:

    In order to include data in the final executable's .data section, you need to first turn that data files (which could be an arbitrary binary file (anything!)) into a linkable file format, also known as an object file.

    The tool objcopy which is included in GNU Binutils and is accessible in windows through Cygwin or MinGW, takes a file and produces an object file. objcopy requires two things to know before generating the object file, the output file format and the output architecture. In order to determine these two things, i check a valid linkable object file with the tool objdump:

    objdump -f main.o
    

    This gives me the following information:

    main.o:     file format pe-x86-64
    architecture: i386:x86-64, flags 0x00000039:
    HAS_RELOC, HAS_DEBUG, HAS_SYMS, HAS_LOCALS
    start address 0x0000000000000000
    

    With this knowledge now i can create the object file:

    objcopy -I binary -O pe-x86-64 -B i386 data_file.data data_file_data.o
    

    In order to handle large number of files, batch files could come in handy.

    I then simply link the produced object file(s) together with my programs source and dereference the pointers that objcopy generated, through the symbols, whose names could easily be queried with:

    objdump -t data_file_data.o
    

    Which results in:

    data_file_data.o:     file format pe-x86-64
    
    SYMBOL TABLE:
    [  0](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000000 _binary_data_file_data_start
    [  1](sec  1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_end
    [  2](sec -1)(fl 0x00)(ty  0)(scl  2) (nx 0) 0x0000000000000006 _binary_data_file_data_size
    

    Practically speaking, the following code works with GCC/G++:

    extern uint8_t data[]   asm("_binary_data_file_data_start");
    extern uint8_t end[]    asm("_binary_data_file_data_end");
    

    And the following with MSVC++:

    extern "C" uint8_t _binary_data_file_data_start[]; // Same name as symbol
    extern "C" uint8_t _binary_data_file_data_end[];   // Same name as symbol
    

    The size of each each file is calculated with:

    _binary_data_file_data_end - _binary_data_file_data_start
    

    You could for example write the data back into a file:

    FILE* file;
    
    file = fopen("data_file_reproduced.data", "wb");
    fwrite(_binary_data_file_data_start,                               //Pointer to data
           1,                                                          //Write block size
           _binary_data_file_data_end - _binary_data_file_data_start,  //Data size
           file);
    
    fclose(file);
    

提交回复
热议问题