Burner
Burner

Reputation: 81

Howto pass commands to the linker script via .pro file (Qt)

I'm using Qt 5.3.2 with GCC 4.8.2. I want to insert via the .pro file (qmake) a section definition to the linker script created by qmake.

What I want to insert:

SECTIONS 
{
.legacy_vars :
{
    *myModule.o (.bss)
    *myModule.o (.data)
}
.everything_else :
{
    * (.bss)
    * (.data)
    * (.text)
}
}

Is this possible? Thanks in advance!

To answer the question "why?":

I have legacy code in my project which I cannot change. But I need to reset its variables to reset its state. At the same time most of them are static and dont have functions to access them. Therefore I want to map the legacy codes variables to a defined section, read them when starting my program and if needed write them back in order to reset this part of the program.

Upvotes: 3

Views: 1123

Answers (1)

Burner
Burner

Reputation: 81

Found a solution:

First of all the "simple linker script examples" I found on the net are not correct/complete/working for a PC application (like this: link). So i did the following:

  1. Read out the default linker script of GCC into a file: "ld --verbose > ld_script.ld"
  2. Removed the leading additional information generated by the verbose command:

    GNU ld (GNU Binutils) 2.24
      Supported emulations:
       i386pe
    using internal linker script:
    ==================================================
    

and at the end:

    ==================================================
  1. Inserted my addition linkage commands into the linker script:

    .data BLOCK(__section_alignment__) : {
        __data_start__ = . ;
        _legacy_code_data_start = . ;
        *legacy_module_first.o(.data*)
        *legacy_module_next.o(.data*)
        *legacy_module_last.o(.data*)
        _legacy_code_data_end = . ;
        *(.data)
        *(.data2)
        *(SORT(.data$*))
        *(.jcr)
        __data_end__ = . ;
        *(.data_cygwin_nocopy)
    }
    

and:

    .bss BLOCK(__section_alignment__) : {
        __bss_start__ = . ;
        _legacy_code_bss_start = . ;
        *legacy_module_first.o(COMMON)
        *legacy_module_first.o(.bss)
        *legacy_module_next.o(COMMON)
        *legacy_module_next.o(.bss)
        *legacy_module_last.o(COMMON)
        *legacy_module_last.o(.bss)
        _legacy_code_bss_end = . ;
        *(.bss)
        *(COMMON)
        __bss_end__ = . ;
    }
  1. Added the script file to the Qt project
  2. Added the linker script to the linkage via the .pro file with:

    QMAKE_LFLAGS += "-T ../pathtoscript/ld_script.ld"
    
  3. Done.

"-T" tells the linker to use the defined file instead of the default one of the linker. Prior this resulted in errors since the linker files I wrote were not complete.

The result is the following and can be seen within a map file (to create a map file use: QMAKE_LFLAGS += "-Wl,-Map=output.map"):

The .data variables of the legacy modules defined in the linker script will be put between the symbols "_legacy_code_data_start" and "_legacy_code_data_end" and the .bss and COMMON variables will be put between the symbols "_legacy_code_bss_start" and "_legacy_code_bss_end". These symbols can be used by declaring them within the C/C++ code with: "extern void * legacy_code_data_start;" and so on. Therefore I'm now able to read these two data blocks and write them back whenever I want.

Upvotes: 1

Related Questions