To add user-defined relocation types to a file two sepecial sections are added to that file: A section named ".customreloc" contains the actual relocations; a section named ".cusrelocinfo" contains data which is referenced by the ".customreloc" sections - such as the "formulas" used for calculating the relocations.
As an example the equivalent of the following C code shall be stored in an object file:
extern char x,y;
short z = (short)((&x)-(&y));
Then the following information may be stored in an x86 assembler file:
.data
z:
.short 0
.section .customreloc
.word 0xE1A5
.byte 33
.byte 16
.long REL_CUSTOM_DIST16_LE
.long z
.long x
.long y
.section .cusrelocinfo
REL_CUSTOM_DIST16_LE:
.asciz "d=b-c;*a=d;*(a+1)=d>>8;"
It is of course also possible to store the relocation formulas (the ".cusrelocinfo" section) in a library file so multiple object files may use the relocation definitions defined in one single object file.
The processuserrel tool is used after linking: It processes the custom relocations found in the two sections and modifies the linker's output. To do so the argument "-p" is used.
Used with the argument "-r" the tool will display all used-defined relocations in the binary file but it won't modify the file.
The 32-bit ELF file variant will also support "-r" for object files however the information returned will be wrong - especially when using an object file using "RELA" type relocations.
The ".customreloc" section contains entries which must be aligned to 4 bytes. Padding bytes may be inserted between the entries (the linker may do this). An entry has the following form:
The entry begins with the 16 bit value 57765 (E1A5 hexadecimal). This number is used to indicate the start of an entry (after padding bytes). The number is also used to indicate if an entry is little or big endian because it is allowed to use big and little endian entries in the same file!
(However this version of processuserrel only supports entries that have the same endiannes than the ELF file!)
The third byte of an entry has the following bits:
The fourth byte of the entry is the length of the entry measured in bytes not including the first four bytes. (In other words: The number of bytes following.)
A "type 1" entry is at least 8 bytes (not including the 4 header bytes) and always a multiple of 4 bytes long.
The first 32-bit word following the 4 header bytes is a pointer to a NUL-terminated string in the ".cusrelocinfo" structure. This string is the "formula" describing how to process the relocation.
The second 32-bit word (typically) is a pointer to the byte or word to be relocated. It is also the initial value of the variable "a" used in the formula in the ".cusrelocinfo" section. (The word may contain some other information if the relocation is not really a relocation but it only contains a check using a "?..." statement.)
The (optional) third 32-bit word is the initial value of the variable "b" which is typically the relocation's target address.
The fourth 32-bit word is the initial value of the variable "c", the fifth 32-bit word is the initial value of the variable "d" and so on.
These strings may be empty (dummy relocation) or they consist of one or more statements which end with a semi-colon. The statements are simply concatenated.
The following statements are defined:
variable=expression;
Assigns a value to a variable. There are 26 variables named "a" to "z" whose data type is 32-bit unsigned integer. As described above the first variables are already initialized with the values from the entry in the ".customreloc" section.
?condition"Error message";
Calculates the condition. If the condition is false an error message will be printed and processing the file fails. The error message may contain space characters (typically it will do). This is the only exception to the rule that the NUL-terminated strings do not contain "whitespace" characters. Qutation marks within the error message are written as two quotation marks. Backslashes are not escaped.
*address=value;
Overwrites the byte at the virtual address given by the low 8 bits of a certain value.
Values use a subset of the C/C++ operators. However there are differences to C/C++:
Constants are specified as decimal numbers.
The following binary C/C++ operators are supported:
+, -, *, /, %, |, &, ^, >>, <<, ==, !=, <=, >=, <, >, &&, ||
The ternary "?:" operator is also supported.
Unary operators (-, ~, !, *) are not supported. (Although "processuserrel.txt" knows the unary "*" operator.)
c=b-a-4;*a=c;*a+1=c>>8;*a+2=c>>16;*a+3=c>>24;
A "8-bit unsigned PC-relative" relocation looks like this:
c=b-a-1;?c<256"The relocation is too far away!";*a=c;
This file is published under the GPLv2 licencse.