Open main menu

Difference between revisions of "HOWTO-Dynamic Modules"

Fix syntax highlighting
(Removed Reference to SVN)
(Fix syntax highlighting)
Line 25: Line 25:


==== Example of foobar-provider.h====
==== Example of foobar-provider.h====
<syntax type="C++">#if defined(DYNAMIC_MODULES) && defined(FOOBAR)
<source lang="cpp">#if defined(DYNAMIC_MODULES) && defined(FOOBAR)


#include "backends/plugins/elf-provider.h"
#include "backends/plugins/elf-provider.h"
Line 45: Line 45:


#endif // defined(DYNAMIC_MODULES) && defined(FOOBAR)
#endif // defined(DYNAMIC_MODULES) && defined(FOOBAR)
</syntax>
</source>


==== Making the plugin linker script for your backend ====
==== Making the plugin linker script for your backend ====
Line 52: Line 52:
*First, you can remove the <tt>ENTRY(symbol)</tt> command. This command normally tells the linker which instruction should be the first to execute in the program, but since you're generating a plugin that will be linked in and jumped to from the main executable, it is not needed.  
*First, you can remove the <tt>ENTRY(symbol)</tt> command. This command normally tells the linker which instruction should be the first to execute in the program, but since you're generating a plugin that will be linked in and jumped to from the main executable, it is not needed.  
*Next, define an ELF program header for a "plugin" segment to be loaded from the file. Do this by adding the following before the SECTIONS command:
*Next, define an ELF program header for a "plugin" segment to be loaded from the file. Do this by adding the following before the SECTIONS command:
<syntax type="C++">PHDRS
<source lang="cpp">PHDRS
{
{
   plugin PT_LOAD ;
   plugin PT_LOAD ;
}</syntax>
}</source>
*Set the start address of the file to be 0 (since this will be linked in at a different address later), usually you can do this by replacing the first line in SECTIONS with <code>. = 0;</code>, though different ld scripts may require different modifications.
*Set the start address of the file to be 0 (since this will be linked in at a different address later), usually you can do this by replacing the first line in SECTIONS with <code>. = 0;</code>, though different ld scripts may require different modifications.
*Place the first section (as listed under the SECTIONS command) into the "plugin" segment you defined in PHDRS by appending <tt>:plugin</tt> to the first sections-command, i.e <code>.text . : { *(.text) } :plugin</code>. As long as there aren't any other PHDRS, this should ensure the entire linked file is put in the "plugin" segment, since future sections assume they are to be put in the same segment as the previous section unless specified otherwise (via <tt>:phdr</tt> or <tt>:NONE</tt>).
*Place the first section (as listed under the SECTIONS command) into the "plugin" segment you defined in PHDRS by appending <tt>:plugin</tt> to the first sections-command, i.e <code>.text . : { *(.text) } :plugin</code>. As long as there aren't any other PHDRS, this should ensure the entire linked file is put in the "plugin" segment, since future sections assume they are to be put in the same segment as the previous section unless specified otherwise (via <tt>:phdr</tt> or <tt>:NONE</tt>).
*Find the <tt>.ctors</tt> and <tt>.dtors</tt> sections (constructors and destructors) and delete any output-section-commands within them that reference crtbegin or crtend, i.e <code>KEEP (*crtbegin*.o(.dtors))</code> or <code>KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))</code>. Put <code>___plugin_ctors = .;</code> as the first output-section-command in the <tt>.ctors</tt> section and <code>___plugin_ctors_end = .;</code> as the last output-section-command. Do the same for the <tt>.dtors</tt> section but with <tt>___plugin_dtors</tt>, etc. This gives these symbols values that our run-time loader can use. In the end, <tt>.ctors</tt> and <tt>.dtors</tt> should look something like this:
*Find the <tt>.ctors</tt> and <tt>.dtors</tt> sections (constructors and destructors) and delete any output-section-commands within them that reference crtbegin or crtend, i.e <code>KEEP (*crtbegin*.o(.dtors))</code> or <code>KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))</code>. Put <code>___plugin_ctors = .;</code> as the first output-section-command in the <tt>.ctors</tt> section and <code>___plugin_ctors_end = .;</code> as the last output-section-command. Do the same for the <tt>.dtors</tt> section but with <tt>___plugin_dtors</tt>, etc. This gives these symbols values that our run-time loader can use. In the end, <tt>.ctors</tt> and <tt>.dtors</tt> should look something like this:
<syntax type="C++">.ctors          :
<source lang="cpp">.ctors          :
{
{
   ___plugin_ctors = .;
   ___plugin_ctors = .;
Line 72: Line 72:
   KEEP (*(.dtors))
   KEEP (*(.dtors))
   ___plugin_dtors_end = .;
   ___plugin_dtors_end = .;
}</syntax>
}</source>
*That's it! If you have trouble with any of these instructions or need to further modify the linker script for something specific to your platform, see [http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts.html] for linker script documentation and peruse the various <tt>plugin.ld</tt> files in the subdirectories of <tt>backends/plugins/</tt>. TODO: Add stuff about MIPS-specific linker script modifications, namely the "shorts" segment.
*That's it! If you have trouble with any of these instructions or need to further modify the linker script for something specific to your platform, see [http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts.html] for linker script documentation and peruse the various <tt>plugin.ld</tt> files in the subdirectories of <tt>backends/plugins/</tt>. TODO: Add stuff about MIPS-specific linker script modifications, namely the "shorts" segment.


Line 78: Line 78:
There will undoubtedly be a number of things specific to your platform to deal with when it comes to modifying the building, but you should definitely add the following, bordered by #ifdef guards to make sure DYNAMIC_MODULES is set to 1 (along with telling the desired engines that you want them to be separate plugin files, i.e. "ENABLE_SCUMM = DYNAMIC_PLUGIN"):
There will undoubtedly be a number of things specific to your platform to deal with when it comes to modifying the building, but you should definitely add the following, bordered by #ifdef guards to make sure DYNAMIC_MODULES is set to 1 (along with telling the desired engines that you want them to be separate plugin files, i.e. "ENABLE_SCUMM = DYNAMIC_PLUGIN"):


<syntax type="C++">DEFINES += ELF_LOADER_TARGET //also add any other necessary defines
<source lang="Makefile">DEFINES += ELF_LOADER_TARGET //also add any other necessary defines
PLUGIN_SUFFIX := .plg //or whatever your suffix is
PLUGIN_SUFFIX := .plg //or whatever your suffix is
PLUGIN_EXTRA_DEPS = $(EXECUTABLE)
PLUGIN_EXTRA_DEPS = $(EXECUTABLE)
Line 84: Line 84:
PRE_OBJS_FLAGS := -Wl,--whole-archive
PRE_OBJS_FLAGS := -Wl,--whole-archive
POST_OBJS_FLAGS := -Wl,--no-whole-archive
POST_OBJS_FLAGS := -Wl,--no-whole-archive
</syntax>
</source>


As you can see, these modifications mainly deal with making sure the plugins are dependent on the main executable and use the custom linker script.
As you can see, these modifications mainly deal with making sure the plugins are dependent on the main executable and use the custom linker script.
TrustedUser
2,147

edits