http://blea.ch/wiki/api.php?action=feedcontributions&user=93.174.93.148&feedformat=atomProjectWiki - User contributions [en]2024-03-28T18:23:16ZUser contributionsMediaWiki 1.18.1http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-11-01T15:43:12Z<p>93.174.93.148: krdsqbfa bgsrannt bttdgfzt</p>
<hr />
<div>krdsqbfa bgsrannt bttdgfzt</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-23T10:13:33Z<p>93.174.93.148: oksnsrsu ycuiczjs zjvaqcql</p>
<hr />
<div>oksnsrsu ycuiczjs zjvaqcql</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-23T08:58:59Z<p>93.174.93.148: yfupyvyl pcqsxsgg fiubqzml</p>
<hr />
<div>yfupyvyl pcqsxsgg fiubqzml</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-23T06:35:43Z<p>93.174.93.148: kcumzzlf adqrjhxh yzkzrhjs</p>
<hr />
<div>kcumzzlf adqrjhxh yzkzrhjs</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-23T05:24:41Z<p>93.174.93.148: upfalewh ngehxyum sqspxzma</p>
<hr />
<div>upfalewh ngehxyum sqspxzma</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-22T01:19:23Z<p>93.174.93.148: zljrujal bofnwzvv ileykooo</p>
<hr />
<div>zljrujal bofnwzvv ileykooo</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-22T00:04:40Z<p>93.174.93.148: dyxcsuwd ioahcfal dcifzzry</p>
<hr />
<div>dyxcsuwd ioahcfal dcifzzry</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-21T22:55:20Z<p>93.174.93.148: nbvkvhxx oglkeitl feedrajx</p>
<hr />
<div>nbvkvhxx oglkeitl feedrajx</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-21T21:48:36Z<p>93.174.93.148: itpzgsgs fidbhtqp zwiabpef</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
iwjzllti oxxawzaa mdpcsagb<br />
<br />
zuhkdnhb vvkefjyx gkkqoqpy<br />
<br />
ldjlijbd qmsbqyha eepzfxmk<br />
<br />
bgfogepf hfxuzqrh wlnxhpax<br />
<br />
itpzgsgs fidbhtqp zwiabpef</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-20T17:06:28Z<p>93.174.93.148: bgfogepf hfxuzqrh wlnxhpax</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
iwjzllti oxxawzaa mdpcsagb<br />
<br />
zuhkdnhb vvkefjyx gkkqoqpy<br />
<br />
ldjlijbd qmsbqyha eepzfxmk<br />
<br />
bgfogepf hfxuzqrh wlnxhpax<br />
<br />
==Modules==<br />
Great!! Now you've got it all loaded and ran it and now dunt need it no more, so now what?! If only there was some scheme to keep track of which object files are loaded and what needs to be done to unload them. Well, this is what modules are for, I will probably base mine on the structure of [http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/moduleLib.html moduleLib]. More on this later..</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-20T14:41:41Z<p>93.174.93.148: ldjlijbd qmsbqyha eepzfxmk</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
iwjzllti oxxawzaa mdpcsagb<br />
<br />
zuhkdnhb vvkefjyx gkkqoqpy<br />
<br />
ldjlijbd qmsbqyha eepzfxmk<br />
<br />
==ARM Thumb insanity==<br />
[[Image:Thlinker.png|right|Simple linking test. :D]]<br />
Immediately one problem became clear, while it worked fine on x86 code, even after adding the required relocation handling code for R_ARM_CALL and R_ARM_ABS32 (this was same as x86 abs32 btw :D) the arm9 linking test wasn't working properly. After digging a bit realized that libnds operates mostly in 16 bit Thumb mode. For this mode R_ARM_THM_PC22 relocation handling was needed.<br />
<br />
To get an idea how arm-eabi handles R_ARM_THM_PC22 i examined elf32-arm.h which contains the processor specific handling code and macros relating to relocation among other things. From this i immediately realized thumb being 16 bit uses two instructions for 'bl' each containing 11 bits representing the branch address and 5 bits for the branch high or branch low instrunctions. (0xf000 and 0xf800) Perfect sense right @_@)? <br />
<br />
<br />
<br />
Below is the source code that was linked into thlink (see image):<br />
<source lang="c"><br />
#include <stdio.h><br />
//Just filler so that otherFunc is offset for better testing<br />
int otherFunc(int argc, char **argv) {<br />
printf("otherFunc!\n");<br />
}<br />
<br />
int someFunc(void) {<br />
printf("Zomg! It Works! ^_^\n");<br />
}<br />
</source><br />
<br />
==Modules==<br />
Great!! Now you've got it all loaded and ran it and now dunt need it no more, so now what?! If only there was some scheme to keep track of which object files are loaded and what needs to be done to unload them. Well, this is what modules are for, I will probably base mine on the structure of [http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/moduleLib.html moduleLib]. More on this later..</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-20T13:30:34Z<p>93.174.93.148: zuhkdnhb vvkefjyx gkkqoqpy</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
iwjzllti oxxawzaa mdpcsagb<br />
<br />
zuhkdnhb vvkefjyx gkkqoqpy<br />
<br />
==Linking==<br />
So first step in loading would be to identify all the loadable sections. The next step is to add all symbols of which the addresses are known from the file to the symbol table, such as any named addresses within the previously loaded sections.<br />
<br />
After loading all the loadable sections and adding known symbols can do final relocation. This involves modifying the relocatable sections marked with RELOC. <br />
<br />
Taking a look at the disassembly of the 'otherFunc' example can see (objdump -d):<br />
* otherFunc starts at 0x00000026 in it's section within the file<br />
* section .rodata + 0xd contains the string to print<br />
* puts has no value set (just -4)<br />
<br />
<source lang="asm"><br />
00000026 <otherFunc>:<br />
26: 55 push %ebp<br />
27: 89 e5 mov %esp,%ebp<br />
29: 83 ec 08 sub $0x8,%esp<br />
2c: c7 04 24 0d 00 00 00 movl $0xd,(%esp)<br />
2f: R_386_32 .rodata<br />
33: e8 fc ff ff ff call 34 <otherFunc+0xe><br />
34: R_386_PC32 puts<br />
38: c9 leave <br />
39: c3 ret <br />
</source><br />
<br />
What needs to now happen is the ram addresses of .rodata and puts functions need to be found and the values within otherFunc replaced with the proper ones. To assist in this is the relocation table section, found immediately following the section marked RELOC (not shown by objdump command?! but its there, trust me.. :P) Entries in this table define what address within the relocatable segment need external references, which symbol should be referenced and how the data should be modified. <br />
<br />
Relocation records for .text section (objdump -r)<br />
<pre><br />
RELOCATION RECORDS FOR [.text]:<br />
OFFSET TYPE VALUE <br />
00000010 R_386_32 .rodata<br />
00000015 R_386_PC32 puts<br />
0000002f R_386_32 .rodata<br />
00000034 R_386_PC32 puts<br />
</pre><br />
<br />
For example lets say:<br />
.rodata section was loaded into address 0x8000<br />
.text (program code) was loaded into 0x8100<br />
<br />
The relocation entry for .text address 0x2f specifies that at that adress there is a 32 bit reference to what was in the .rodata section.(the text "Hai2u! \^_^\n"). Since we have loaded them previously .text is now at 0x8100 so 0x2f becomes 0x8100+0x2f, and .rodata is now at 0x8000. These name/value pairs are also added to the system serial table. <br />
<br />
The linker needs to modify 0x812f to contain the proper address for .rodata (found by looking in the running system's symbol table since it was already added during a previous phase) which is 0x8000. But if you look the original value at that locaion is 0xd! This is because this value is intended to be added with whatever symbol value is requested, so finally... the proper address to write to 0x812f would be 0x8000+0xd or 0x800d :D<br />
<br />
For the value of 'puts', first it looks up where puts is in the system's symbol table. Since the relocation entry specifies it is R_386_PC32 this means the value is to be program counter relative (PC + value == call address). So to figure out the proper value it takes the address value of the symbol puts (for sake of demonstration lets say its at 0x70f4) minus the address value of the instruction (0x8134) and finally add on whatever original value was in the location... so: 0x70f4 - 0x8134 + 0xfffffffc (0xfffffffc == -4), or symaddr - relocaddr + original value; <br />
<br />
Now that function is loaded in ram and linked into all the other parts of the current system it needs. The otherFunc now can be called by looking up the symbol value address 'otherFunc' and casting it as a function:<br />
<source lang="c"><br />
typedef void(*_someFunc)(void);<br />
...<br />
((_someFunc)value)();<br />
</source><br />
<br />
Makes perfect sense right! u_u;;;;<br />
<br />
==ARM Thumb insanity==<br />
[[Image:Thlinker.png|right|Simple linking test. :D]]<br />
Immediately one problem became clear, while it worked fine on x86 code, even after adding the required relocation handling code for R_ARM_CALL and R_ARM_ABS32 (this was same as x86 abs32 btw :D) the arm9 linking test wasn't working properly. After digging a bit realized that libnds operates mostly in 16 bit Thumb mode. For this mode R_ARM_THM_PC22 relocation handling was needed.<br />
<br />
To get an idea how arm-eabi handles R_ARM_THM_PC22 i examined elf32-arm.h which contains the processor specific handling code and macros relating to relocation among other things. From this i immediately realized thumb being 16 bit uses two instructions for 'bl' each containing 11 bits representing the branch address and 5 bits for the branch high or branch low instrunctions. (0xf000 and 0xf800) Perfect sense right @_@)? <br />
<br />
<br />
<br />
Below is the source code that was linked into thlink (see image):<br />
<source lang="c"><br />
#include <stdio.h><br />
//Just filler so that otherFunc is offset for better testing<br />
int otherFunc(int argc, char **argv) {<br />
printf("otherFunc!\n");<br />
}<br />
<br />
int someFunc(void) {<br />
printf("Zomg! It Works! ^_^\n");<br />
}<br />
</source><br />
<br />
==Modules==<br />
Great!! Now you've got it all loaded and ran it and now dunt need it no more, so now what?! If only there was some scheme to keep track of which object files are loaded and what needs to be done to unload them. Well, this is what modules are for, I will probably base mine on the structure of [http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/moduleLib.html moduleLib]. More on this later..</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-10-20T12:21:05Z<p>93.174.93.148: iwjzllti oxxawzaa mdpcsagb</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
iwjzllti oxxawzaa mdpcsagb<br />
<br />
==Extended Linker Format (elf)==<br />
When the compiler runs it does not know where these sections will be in RAM, so it instead provides references to locations within the object file of data or other functions from this file, and indicates when a symbol's value is unknown and must be provided externally. The format of these outputted files is typically ELF or Extended Linker Format. <br />
<br />
The ELF file is divided into a number of parts, first there is the elf header (Elf32_Ehdr) which defines the number and location of the section and program segments. next there are the program segments which contain prelinked absolute data, and section segments. These are both described using program (Elf32_Shdr) and section (Elf32_Phdr) headers respectively. Definitions of these structures is in elf.h which varies from build to build of binutils/gcc toolchain. Because the elf format works equally well with all CPUs, and most operating systems there are many many variants such as 32 and 64 bit, arm, mips, x86 cpu etc. <br />
<br />
The specifics of which system a particular elf object file are for as well as which version of the toolchain was used to compile it is are found in the elf header. These should be checked for compatibility before linking. <br />
<br />
Sections within the object file contain data of various types. Some is actual data or code to be linked, others contain information about how to link the code or data, even others describe the symbol table, etc etc.<br />
<br />
Sections from a typical ELF file (found using objdump -h):<br />
<pre><br />
Sections:<br />
Idx Name Size VMA LMA File off Algn<br />
0 .text 0000003a 00000000 00000000 00000034 2**2<br />
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE<br />
1 .data 00000000 00000000 00000000 00000070 2**2<br />
CONTENTS, ALLOC, LOAD, DATA<br />
2 .bss 00000000 00000000 00000000 00000070 2**2<br />
ALLOC<br />
3 .debug_abbrev 0000007d 00000000 00000000 00000070 2**0<br />
CONTENTS, READONLY, DEBUGGING<br />
4 .debug_info 0000019f 00000000 00000000 000000ed 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
5 .debug_line 0000003b 00000000 00000000 0000028c 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
6 .rodata 00000018 00000000 00000000 000002c7 2**0<br />
CONTENTS, ALLOC, LOAD, READONLY, DATA<br />
7 .debug_frame 00000054 00000000 00000000 000002e0 2**2<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
8 .debug_loc 00000058 00000000 00000000 00000334 2**0<br />
CONTENTS, READONLY, DEBUGGING<br />
9 .debug_pubnames 0000002d 00000000 00000000 0000038c 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
10 .debug_aranges 00000020 00000000 00000000 000003b9 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
11 .comment 0000002a 00000000 00000000 000003d9 2**0<br />
CONTENTS, READONLY<br />
12 .note.GNU-stack 00000000 00000000 00000000 00000403 2**0<br />
CONTENTS, READONLY<br />
</pre><br />
<br />
For most applications you can ignore the .debug* sections, these are not normally used for linking but instead for gdb. Sections within the file which are to be linked are marked as "LOAD" (SHF_ALLOC). Sections with an accompanying relocate table are marked as "RELOC" (SHF_ALLOC?), the allocation table seems to always follow in the section immediately following it.<br />
<br />
The definitions for headers are system and version specific, however mostly interchangeable. For instance for testing I used my /usr/include/'''elf.h''' from standard Ubuntu Linux distro and just added some ARM specific defines from another file and it worked fine. Another file of interest is elf32-arm.h (or elf32-x86.h) but more on that later... ^^<br />
<br />
==Linking==<br />
So first step in loading would be to identify all the loadable sections. The next step is to add all symbols of which the addresses are known from the file to the symbol table, such as any named addresses within the previously loaded sections.<br />
<br />
After loading all the loadable sections and adding known symbols can do final relocation. This involves modifying the relocatable sections marked with RELOC. <br />
<br />
Taking a look at the disassembly of the 'otherFunc' example can see (objdump -d):<br />
* otherFunc starts at 0x00000026 in it's section within the file<br />
* section .rodata + 0xd contains the string to print<br />
* puts has no value set (just -4)<br />
<br />
<source lang="asm"><br />
00000026 <otherFunc>:<br />
26: 55 push %ebp<br />
27: 89 e5 mov %esp,%ebp<br />
29: 83 ec 08 sub $0x8,%esp<br />
2c: c7 04 24 0d 00 00 00 movl $0xd,(%esp)<br />
2f: R_386_32 .rodata<br />
33: e8 fc ff ff ff call 34 <otherFunc+0xe><br />
34: R_386_PC32 puts<br />
38: c9 leave <br />
39: c3 ret <br />
</source><br />
<br />
What needs to now happen is the ram addresses of .rodata and puts functions need to be found and the values within otherFunc replaced with the proper ones. To assist in this is the relocation table section, found immediately following the section marked RELOC (not shown by objdump command?! but its there, trust me.. :P) Entries in this table define what address within the relocatable segment need external references, which symbol should be referenced and how the data should be modified. <br />
<br />
Relocation records for .text section (objdump -r)<br />
<pre><br />
RELOCATION RECORDS FOR [.text]:<br />
OFFSET TYPE VALUE <br />
00000010 R_386_32 .rodata<br />
00000015 R_386_PC32 puts<br />
0000002f R_386_32 .rodata<br />
00000034 R_386_PC32 puts<br />
</pre><br />
<br />
For example lets say:<br />
.rodata section was loaded into address 0x8000<br />
.text (program code) was loaded into 0x8100<br />
<br />
The relocation entry for .text address 0x2f specifies that at that adress there is a 32 bit reference to what was in the .rodata section.(the text "Hai2u! \^_^\n"). Since we have loaded them previously .text is now at 0x8100 so 0x2f becomes 0x8100+0x2f, and .rodata is now at 0x8000. These name/value pairs are also added to the system serial table. <br />
<br />
The linker needs to modify 0x812f to contain the proper address for .rodata (found by looking in the running system's symbol table since it was already added during a previous phase) which is 0x8000. But if you look the original value at that locaion is 0xd! This is because this value is intended to be added with whatever symbol value is requested, so finally... the proper address to write to 0x812f would be 0x8000+0xd or 0x800d :D<br />
<br />
For the value of 'puts', first it looks up where puts is in the system's symbol table. Since the relocation entry specifies it is R_386_PC32 this means the value is to be program counter relative (PC + value == call address). So to figure out the proper value it takes the address value of the symbol puts (for sake of demonstration lets say its at 0x70f4) minus the address value of the instruction (0x8134) and finally add on whatever original value was in the location... so: 0x70f4 - 0x8134 + 0xfffffffc (0xfffffffc == -4), or symaddr - relocaddr + original value; <br />
<br />
Now that function is loaded in ram and linked into all the other parts of the current system it needs. The otherFunc now can be called by looking up the symbol value address 'otherFunc' and casting it as a function:<br />
<source lang="c"><br />
typedef void(*_someFunc)(void);<br />
...<br />
((_someFunc)value)();<br />
</source><br />
<br />
Makes perfect sense right! u_u;;;;<br />
<br />
==ARM Thumb insanity==<br />
[[Image:Thlinker.png|right|Simple linking test. :D]]<br />
Immediately one problem became clear, while it worked fine on x86 code, even after adding the required relocation handling code for R_ARM_CALL and R_ARM_ABS32 (this was same as x86 abs32 btw :D) the arm9 linking test wasn't working properly. After digging a bit realized that libnds operates mostly in 16 bit Thumb mode. For this mode R_ARM_THM_PC22 relocation handling was needed.<br />
<br />
To get an idea how arm-eabi handles R_ARM_THM_PC22 i examined elf32-arm.h which contains the processor specific handling code and macros relating to relocation among other things. From this i immediately realized thumb being 16 bit uses two instructions for 'bl' each containing 11 bits representing the branch address and 5 bits for the branch high or branch low instrunctions. (0xf000 and 0xf800) Perfect sense right @_@)? <br />
<br />
<br />
<br />
Below is the source code that was linked into thlink (see image):<br />
<source lang="c"><br />
#include <stdio.h><br />
//Just filler so that otherFunc is offset for better testing<br />
int otherFunc(int argc, char **argv) {<br />
printf("otherFunc!\n");<br />
}<br />
<br />
int someFunc(void) {<br />
printf("Zomg! It Works! ^_^\n");<br />
}<br />
</source><br />
<br />
==Modules==<br />
Great!! Now you've got it all loaded and ran it and now dunt need it no more, so now what?! If only there was some scheme to keep track of which object files are loaded and what needs to be done to unload them. Well, this is what modules are for, I will probably base mine on the structure of [http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/moduleLib.html moduleLib]. More on this later..</div>93.174.93.148http://blea.ch/wiki/index.php/Elf_linkingElf linking2011-09-21T15:24:25Z<p>93.174.93.148: /* What is this */</p>
<hr />
<div><big>Adventures in dynamic linking</big><br />
__TOC__<br />
Bab8yL qlxemglc wiqanrkf pwntokfj<br />
<br />
==Symbols==<br />
First it needs some way to identify locations in memory. This is accomplished with '''symbols'''. A symbol is a reference to a location in memory and minimally contains location of the symbol, and a textual name for the symbol. It may also contain information about the type of symbol (program, data, global data, etc), who (or which process) owns the symbol, which section of the object file the symbol came from, group it belongs to, etc. <br />
<br />
<source lang="c"><br />
//Typical symbol table<br />
typedef struct _SYMBOL {<br />
char *name;<br />
char *value;<br />
SYM_TYPE type;<br />
UINT16 group;<br />
} SYMBOL;<br />
</source><br />
<br />
Many schemes exist for symbol table implementation, some use a hash table for quicker lookups, some use linked lists while others have a finite array. They all do the same thing, which is, to provide a database relating addresses to names. My implementation is based of VxWork's symLib. But anyways, what about linking?<br />
<br />
==Extended Linker Format (elf)==<br />
When the compiler runs it does not know where these sections will be in RAM, so it instead provides references to locations within the object file of data or other functions from this file, and indicates when a symbol's value is unknown and must be provided externally. The format of these outputted files is typically ELF or Extended Linker Format. <br />
<br />
The ELF file is divided into a number of parts, first there is the elf header (Elf32_Ehdr) which defines the number and location of the section and program segments. next there are the program segments which contain prelinked absolute data, and section segments. These are both described using program (Elf32_Shdr) and section (Elf32_Phdr) headers respectively. Definitions of these structures is in elf.h which varies from build to build of binutils/gcc toolchain. Because the elf format works equally well with all CPUs, and most operating systems there are many many variants such as 32 and 64 bit, arm, mips, x86 cpu etc. <br />
<br />
The specifics of which system a particular elf object file are for as well as which version of the toolchain was used to compile it is are found in the elf header. These should be checked for compatibility before linking. <br />
<br />
Sections within the object file contain data of various types. Some is actual data or code to be linked, others contain information about how to link the code or data, even others describe the symbol table, etc etc.<br />
<br />
Sections from a typical ELF file (found using objdump -h):<br />
<pre><br />
Sections:<br />
Idx Name Size VMA LMA File off Algn<br />
0 .text 0000003a 00000000 00000000 00000034 2**2<br />
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE<br />
1 .data 00000000 00000000 00000000 00000070 2**2<br />
CONTENTS, ALLOC, LOAD, DATA<br />
2 .bss 00000000 00000000 00000000 00000070 2**2<br />
ALLOC<br />
3 .debug_abbrev 0000007d 00000000 00000000 00000070 2**0<br />
CONTENTS, READONLY, DEBUGGING<br />
4 .debug_info 0000019f 00000000 00000000 000000ed 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
5 .debug_line 0000003b 00000000 00000000 0000028c 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
6 .rodata 00000018 00000000 00000000 000002c7 2**0<br />
CONTENTS, ALLOC, LOAD, READONLY, DATA<br />
7 .debug_frame 00000054 00000000 00000000 000002e0 2**2<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
8 .debug_loc 00000058 00000000 00000000 00000334 2**0<br />
CONTENTS, READONLY, DEBUGGING<br />
9 .debug_pubnames 0000002d 00000000 00000000 0000038c 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
10 .debug_aranges 00000020 00000000 00000000 000003b9 2**0<br />
CONTENTS, RELOC, READONLY, DEBUGGING<br />
11 .comment 0000002a 00000000 00000000 000003d9 2**0<br />
CONTENTS, READONLY<br />
12 .note.GNU-stack 00000000 00000000 00000000 00000403 2**0<br />
CONTENTS, READONLY<br />
</pre><br />
<br />
For most applications you can ignore the .debug* sections, these are not normally used for linking but instead for gdb. Sections within the file which are to be linked are marked as "LOAD" (SHF_ALLOC). Sections with an accompanying relocate table are marked as "RELOC" (SHF_ALLOC?), the allocation table seems to always follow in the section immediately following it.<br />
<br />
The definitions for headers are system and version specific, however mostly interchangeable. For instance for testing I used my /usr/include/'''elf.h''' from standard Ubuntu Linux distro and just added some ARM specific defines from another file and it worked fine. Another file of interest is elf32-arm.h (or elf32-x86.h) but more on that later... ^^<br />
<br />
==Linking==<br />
So first step in loading would be to identify all the loadable sections. The next step is to add all symbols of which the addresses are known from the file to the symbol table, such as any named addresses within the previously loaded sections.<br />
<br />
After loading all the loadable sections and adding known symbols can do final relocation. This involves modifying the relocatable sections marked with RELOC. <br />
<br />
Taking a look at the disassembly of the 'otherFunc' example can see (objdump -d):<br />
* otherFunc starts at 0x00000026 in it's section within the file<br />
* section .rodata + 0xd contains the string to print<br />
* puts has no value set (just -4)<br />
<br />
<source lang="asm"><br />
00000026 <otherFunc>:<br />
26: 55 push %ebp<br />
27: 89 e5 mov %esp,%ebp<br />
29: 83 ec 08 sub $0x8,%esp<br />
2c: c7 04 24 0d 00 00 00 movl $0xd,(%esp)<br />
2f: R_386_32 .rodata<br />
33: e8 fc ff ff ff call 34 <otherFunc+0xe><br />
34: R_386_PC32 puts<br />
38: c9 leave <br />
39: c3 ret <br />
</source><br />
<br />
What needs to now happen is the ram addresses of .rodata and puts functions need to be found and the values within otherFunc replaced with the proper ones. To assist in this is the relocation table section, found immediately following the section marked RELOC (not shown by objdump command?! but its there, trust me.. :P) Entries in this table define what address within the relocatable segment need external references, which symbol should be referenced and how the data should be modified. <br />
<br />
Relocation records for .text section (objdump -r)<br />
<pre><br />
RELOCATION RECORDS FOR [.text]:<br />
OFFSET TYPE VALUE <br />
00000010 R_386_32 .rodata<br />
00000015 R_386_PC32 puts<br />
0000002f R_386_32 .rodata<br />
00000034 R_386_PC32 puts<br />
</pre><br />
<br />
For example lets say:<br />
.rodata section was loaded into address 0x8000<br />
.text (program code) was loaded into 0x8100<br />
<br />
The relocation entry for .text address 0x2f specifies that at that adress there is a 32 bit reference to what was in the .rodata section.(the text "Hai2u! \^_^\n"). Since we have loaded them previously .text is now at 0x8100 so 0x2f becomes 0x8100+0x2f, and .rodata is now at 0x8000. These name/value pairs are also added to the system serial table. <br />
<br />
The linker needs to modify 0x812f to contain the proper address for .rodata (found by looking in the running system's symbol table since it was already added during a previous phase) which is 0x8000. But if you look the original value at that locaion is 0xd! This is because this value is intended to be added with whatever symbol value is requested, so finally... the proper address to write to 0x812f would be 0x8000+0xd or 0x800d :D<br />
<br />
For the value of 'puts', first it looks up where puts is in the system's symbol table. Since the relocation entry specifies it is R_386_PC32 this means the value is to be program counter relative (PC + value == call address). So to figure out the proper value it takes the address value of the symbol puts (for sake of demonstration lets say its at 0x70f4) minus the address value of the instruction (0x8134) and finally add on whatever original value was in the location... so: 0x70f4 - 0x8134 + 0xfffffffc (0xfffffffc == -4), or symaddr - relocaddr + original value; <br />
<br />
Now that function is loaded in ram and linked into all the other parts of the current system it needs. The otherFunc now can be called by looking up the symbol value address 'otherFunc' and casting it as a function:<br />
<source lang="c"><br />
typedef void(*_someFunc)(void);<br />
...<br />
((_someFunc)value)();<br />
</source><br />
<br />
Makes perfect sense right! u_u;;;;<br />
<br />
==ARM Thumb insanity==<br />
[[Image:Thlinker.png|right|Simple linking test. :D]]<br />
Immediately one problem became clear, while it worked fine on x86 code, even after adding the required relocation handling code for R_ARM_CALL and R_ARM_ABS32 (this was same as x86 abs32 btw :D) the arm9 linking test wasn't working properly. After digging a bit realized that libnds operates mostly in 16 bit Thumb mode. For this mode R_ARM_THM_PC22 relocation handling was needed.<br />
<br />
To get an idea how arm-eabi handles R_ARM_THM_PC22 i examined elf32-arm.h which contains the processor specific handling code and macros relating to relocation among other things. From this i immediately realized thumb being 16 bit uses two instructions for 'bl' each containing 11 bits representing the branch address and 5 bits for the branch high or branch low instrunctions. (0xf000 and 0xf800) Perfect sense right @_@)? <br />
<br />
<br />
<br />
Below is the source code that was linked into thlink (see image):<br />
<source lang="c"><br />
#include <stdio.h><br />
//Just filler so that otherFunc is offset for better testing<br />
int otherFunc(int argc, char **argv) {<br />
printf("otherFunc!\n");<br />
}<br />
<br />
int someFunc(void) {<br />
printf("Zomg! It Works! ^_^\n");<br />
}<br />
</source><br />
<br />
==Modules==<br />
Great!! Now you've got it all loaded and ran it and now dunt need it no more, so now what?! If only there was some scheme to keep track of which object files are loaded and what needs to be done to unload them. Well, this is what modules are for, I will probably base mine on the structure of [http://www.slac.stanford.edu/exp/glast/flight/sw/vxdocs/vxworks/ref/moduleLib.html moduleLib]. More on this later..</div>93.174.93.148