COFF x86_64 relocation types - linker

I am working on linker development for an open source project. The target architecture is AMD_X86_X64. In AMD_X86_X64 specification The relocation types' calculations for ELF are declared for example, R_X86_64_64
the calculation is S + A. How to do these calculations in COFF I can't find them online ?

COFF relocation types are enumerated at COFF Relocations for x64.
IMAGE_REL_AMD64_ABSOLUTE corresponds with R_X86_X64_COPY (no relocation),
IMAGE_REL_AMD64_ADDR64 corresponds with R_X86_X64_64 (S+A),
IMAGE_REL_AMD64_ADDR32 corresponds with R_X86_X64_32 (S+A),
IMAGE_REL_AMD64_REL32 corresponds with R_X86_X64_PC32 (S+A-P).

Related

C program with big arrays compilation under Windows

In my project in C, I have a third-party library where big arrays (>13 000 000 elements) are used.
real_t T[NVCMIN*NVCMIN]; /**< Reverse triangular matrix, A = [0 T]*Q'. */
real_t Q[NVMAX*NVMAX]; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */
Under Linux, everything works fine with -mcmodel=large.
But under windows, I get bss section errors like this.
Error:
/cygdrive/project/embeddedLapack/qpOASES/Source/OQPinterface.c:218:(.text+0x879): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
/cygdrive/project/embeddedLapack/qpOASES/Source/OQPinterface.c:219:(.text+0x8a9): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
/cygdrive/project/embeddedLapack/qpOASES/Source/OQPinterface.c:260:(.text+0xd18): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
out/objs/mpc_controller_test_ef.o: in function `mpc_controller_ef':
/cygdrive/project/tests/mpc_controller_test_ef.c:163:(.text+0x35d): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
/cygdrive/project/tests/mpc_controller_test_ef.c:276:(.text+0xb01): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
/cygdrive/project/tests/mpc_controller_test_ef.c:276:(.text+0xbab): relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.bss'
/cygdrive/project/tests/mpc_controller_test_ef.c:528:(.text+0x13c7): additional relocation overflows omitted from the output
Options
-mcmodel=medium
Generate code for the medium model: the program is linked in
the lower 2 GB of the address space. Small symbols are also
placed there. Symbols with sizes larger than
-mlarge-data-threshold are put into large data or BSS
sections and can be located above 2GB. Programs can be
statically or dynamically linked.
-mcmodel=large
Generate code for the large model. This model makes no
assumptions about addresses and sizes of sections.
I tried this compiler options under windows:
-Wl,--stack,8589934592 -mcmodel=large
and
-Wl,--stack,8589934592 -mcmodel=medium -mlarge-data-threshold=60000
By decreasing arrays I am able to compile. But I am limmited to 2GB. It looks like the compiler is not using -mcmodel=large
text data bss dec hex filename
833917 8784 2141833472 2142676173 7fb6a4cd .\out\mpc_c.exe

binutils-relocation types in the program linking process for arm32 target

Recently, I have been studying the relocation types in the program linking process for arm32 target.
I have tested some little programs to produce different relocation types to analyze.
And I found some of the relocation types are difficult to produce, such as R_ARM_ABS16, R_ARM_ABS12, R_ARM_THM_ABS5 and R_ARM_ABS8.
I have tried many times and none of them can be produced. I also tried to analyze the source codes of binutils (version 2.26). But no clues can be found how these types are generated in the relocation method elf32_arm_final_link_relocate() in file elf32-arm.c. Or maybe I am just not familiar with the source code and ommit some points.
Does someone know what are these four relocation types for? How can I produce them? Any suggestion is welcomed.
By the way, in the document link below, there are relocation type descriptions for arm32 target.
All my relocation knowledge is come from this document.
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf

Linker (ld) ELF Questions

I have an issue with an ELF file generated by the GNU linker ld.
The result is that the data section (.data) gets corrupted when the executable is loaded into memory. The corruption to the .data section occurs when the loader performs the relocation on the .eh_frame section using the relocation data (.rela.eh_frame).
What happens is that this relocation causes seven writes that are beyond the .eh_frame section and over-write the correct contents of the .data section which is adjacent to the top of the .eh_frame section.
After some investigation, I believe the loader is behaving correctly, but the ELF file it has been given contains an error.
But I could be wrong and wanted to check what I've found so far.
Using readelf on the ELF file, it can be seen that seven of the entries in the .rela.eh_frame section contain offsets that are outside (above) the range given by readelf for the .eh_frame section. ie The seven offsets in .rela.eh_frame are greater than the length given for .eh_frame. When these seven offsets are applied in the relocation, they corrupt the .data section.
So my questions are:
(1) Is my deduction that relocation offsets should not be greater than the length of the section to which they apply? And therefore the ELF file that has been generated is in error?
(2) What are people's opinions on the best way of proceeding to diagnose the cause of the incorrect ELF file? Are there any options to ld that will help, or any options that will remove/fix the .eh_frame and it's relocation counterpart .rela.eh_frame?
(3) How would I discover what linker script is being used when the ELF file is generated?
(4) Is there a specific forum where I might find a whole pile of linker experts who would be able to help. I appreciate this is a highly technical question and that many people may not have a clue what I'm talking about!
Thanks for any help!
The .eh_frame section is not supposed to have any run-time relocations. All offsets are fixed when the link editor is run (because the object layout is completely known at this point) and the ET_EXEC or ET_DYN object is created. Only ET_REL objects have relocations in that section, and those are never seen by the dynamic linker. So something odd most be going on.
You can ask such questions on the binutils list or the libc-help list (if you use the GNU toolchain).
EDIT It seems that you are using a toolchain configured for ZCX exceptions with a target which expects SJLJ exceptions. AdaCore has some documentation about his:
GNAT User's Guide Supplement for Cross Platforms 19.0w documentation » VxWorks Topics
Zero Cost Exceptions on PowerPC Targets
It doesn't quite say how t switch to the SJLJ-based VxWorks 5 toolchain. It is definitely not a matter of using the correct linker script. The choice of exception handling style affects code generation, too.

Disassemble, modify, and reassemble executable

How can I disassemble an executable on my mac using ndisasm and reassemble and link it using nasm and ld?
This is what I tried (I'm running MacOS X btw):
*ndisasm a.out | cut -c 29- > main.asm*
this generated clean assembler code with all the processor instructions in main.asm
*nasm -f macho main.asm*
this generated an object file main.o which I then tried to link
*ld main.o*
... this is where I'm stuck. I don't know why it generates the following error:
ld: in section __TEXT,__text reloc 0: R_ABS reloc but no absolute symbol at target adress file 'main.o' for inferred architecture i386.
I also tried specifying the architecture (ld -arch x86_64 main.o) but that didn't work either.
My goal is to disassemble any executable, modify it and then reassemble it again.
What am I doing wrong?
There is no reliable way to do this with normal assembler syntax. See How to disassemble, modify and then reassemble a Linux executable?. Section info is typically not faithfully disassembled, so you'd need a special format designed for modify and reassembling + relinking.
Also, instruction-lengths are a problem when code only works when padded by using longer encodings. (e.g. in a table of jump targets for a computed goto). See Where are GNU assembler instruction suffixes like ".s" in x86 "mov.s" documented?, but note that disassemblers don't support disassembling into that format.
ndisasm doesn't understand object file formats, so it disassembles headers as machine code!
For this to have any hope of working, use a disassembler like Agner Fog's objconv which will output asm source (NASM, MASM, or GAS AT&T) which does assemble. It might not actually work if any of the code depended on a specific longer-than-default encoding.
I'm not sure how faithful objconv is with respect to emitting section .bss, section .rodata and other directives like that to place data where it found it in the object file, but that's what you need.
Re: absolute relocations: make sure you put DEFAULT REL at the top of your file. I forget if objconv does this by default. x86-64 Mach-o only supports PC-relative relocations, so you have to create position-independent code (e.g. using RIP-relative addressing modes).
ndisasm doesn't read the symbol table, so all its operands use absolute addressing. objconv makes up label names for jump targets and static data that doesn't appear in the symbol table.

ELF relocation on ARM Cortex-M3

I'm trying to figure out how relocation works, but I can't seem to get my head around it.
This document describes the different types one can encounter when relocating an ELF file.
Let's take R_ARM_ALU_SB_G0_NC (#70) for example.
Type: static
Class: ARM, describes the type of place being relocated (which I do not understand)
Operation: ((S + A) | T) – B(S))
I'm guessing that the mathematical expression is the operation I'm looking for. However, I do not completely understand how this fits in my function.
The method where the relocation takes place looks as follows:
int elfloader_arch_relocate(int input_fd, struct elfloader_output *output,
unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr)
input_fd is a file descriptor for the ELF file, *output is used when writing the output segment, sectionoffset is the file offset at which the relocation can be found, *sectionaddr is the section start address (absolute runtime) and *addr is the relocated address.
The 32-bit relocation structure looks like this
struct elf32_rela {
elf32_addr r_offset;
elf32_word r_info;
elf32_sword r_addend;
};
On page 26 of the above mentioned document the nomenclature is explained:
S (when used on its own) is the address of the symbol.
A is the addend for the relocation.
T is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 otherwise.
B(S) is the addressing origin of the output segment defining the symbol
So my question is, which of the parameters in the relocate function correspond to the ones used in the formula?
If I'm reading this right, and I'm not sure I am, it goes like this:
S is addr.
B(S) is sectionaddr.
A is rela->r_addend.
T may be derivable from information in rela->r_info; if not, I don't know where you need to look.
This is a really complicated-looking relocation. Consider starting with the simple ones (like R_ARM_ABS16). In a dynamic loader, you should not have to implement all of the relocation typess in the spec you linked to, only a small subset. If it seems like you need a lot of relocation types, this is probably because you are trying to feed unlinked object files to the dynamic loader; you should turn them into shared objects, using your existing ARM linker. (With the GNU toolchain, a first approximation to how you do that is gcc -shared foo.o -o foo.so.)
Cribbing off an existing dynamic loader for the architecture is often a good plan; there tends to be a lot of undocumented wisdom buried in the code for such things. For instance, here is GNU libc's ld.so's ARM relocator. (LGPL)

Resources