Patching symbols

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
srg

Patching symbols

Post by srg »

Hi

In dynamic linking, when relocations are patched, are all calls and instructions with memory access edited with the new base address of the library in memory plus the offset of the symbol, so global variable access and jumps go to the right place?

Or is there another way?

srg
Dreamsmith

Re:Patching symbols

Post by Dreamsmith »

srg wrote:Or is there another way?
There is another way. You create a table, and calls to dynamic library routines don't call the address of a routine directly, but instead call through the address in the table. Then, during dynamic linking, you don't have to modify the code, just the table it points to. I believe dynamic linking on ELF systems does it this way, but I'm not entirely sure...

The advantage is, this works with "Harvard architecture", where you cannot write into code memory. You could even dynamically link ROM code with a minor bit of work. The disadvantage is, it adds a level of indirection.
srg

Re:Patching symbols

Post by srg »

Dreamsmith wrote:
srg wrote:Or is there another way?
There is another way. You create a table, and calls to dynamic library routines don't call the address of a routine directly, but instead call through the address in the table. Then, during dynamic linking, you don't have to modify the code, just the table it points to. I believe dynamic linking on ELF systems does it this way, but I'm not entirely sure...

The advantage is, this works with "Harvard architecture", where you cannot write into code memory. You could even dynamically link ROM code with a minor bit of work. The disadvantage is, it adds a level of indirection.
Does this work for global variables?

If so, is there any information arround which will give me an illustration of all this

also, what about calls from one library routine to another library routine?

Unless you document that (this is for my os's device drivers) the driver developer must call pointers to functions and pointers to global data (it just doesn't seem very elegant).

thanks
srg
Dreamsmith

Re:Patching symbols

Post by Dreamsmith »

Global variables are handled somewhat differently, at least under ELF shared libraries. Found this link with the details:

http://www.iecc.com/linker/linker10.html

Elegant? Probably not. Calling pointers to functions and such is really, when you get right down to it, exactly what is happening in the case of shared library functions, and something even more cumbersome when it comes to global variables, the compiler and linker are just conspiring to hide the details...
srg

Re:Patching symbols

Post by srg »

Dreamsmith wrote: Global variables are handled somewhat differently, at least under ELF shared libraries. Found this link with the details:

http://www.iecc.com/linker/linker10.html

Elegant? Probably not. Calling pointers to functions and such is really, when you get right down to it, exactly what is happening in the case of shared library functions, and something even more cumbersome when it comes to global variables, the compiler and linker are just conspiring to hide the details...
Ahh yes, I have that book, ELF shared libraries are particularly ugly on the x86 because of the ebp register being used for the GOT.

So the answer is using pointers, I'll just have to document it well when it comes to writing a DDK for my OS. Being a faily raw custom object format, there is no compiler and linker support, hence the burdan on the programmer.

In some ways, I can see now how Linux has traditionally had compiled in drivers rather than shared libraries :) (appart from UNIX tradition.) Shared libraries are a pain.

thanks
srg
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Patching symbols

Post by Pype.Clicker »

note, afaik, the GOT-register is *ebx*, not ebp ... but that doesn't really matters...

Indeed, using ELF shared libraries for drivers is a pain, and imho doesn't worth the investment. They only become *really* helpful when your object is *shared* by several process and that all those process cannot agree on a single target address for the stuff.

In other cases, relocating the object at load-time is the option to be preffered (imho again :)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Patching symbols

Post by Candy »

Pype.Clicker wrote: note, afaik, the GOT-register is *ebx*, not ebp ... but that doesn't really matters...

Indeed, using ELF shared libraries for drivers is a pain, and imho doesn't worth the investment. They only become *really* helpful when your object is *shared* by several process and that all those process cannot agree on a single target address for the stuff.

In other cases, relocating the object at load-time is the option to be preffered (imho again :)
and afaik the EBX register contained the offset of the segments of the code etc. compared to a common base, not necessarily any of the aligned points (could be halfway across an instruction), to make most indexes shorter using signed offsets. The GOT is hardcoded at a certain location during loading, even got 2 special GOT-only relocation types on X86 ELF (plus same on X86-64 ELF, maybe too on IA64 ELF but not sure). It doesn't have a special register for it alone, and if any it'd be EDI or EDX, not EBP. Think of the waste of all the SS-segment prefixes on accessing stack data :) (which everybody takes for granted btw, me too...)
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Patching symbols

Post by Candy »

srg wrote: Hi

In dynamic linking, when relocations are patched, are all calls and instructions with memory access edited with the new base address of the library in memory plus the offset of the symbol, so global variable access and jumps go to the right place?
Should've replied before...

Normal loading -> patching all relocations to point to the right place, load all in place, add swap entries (if necessary that is, to make it swappable), start program

dynamic loading (hope to get it right, thinking X86 ELF here) :

File is loaded verbatim, section by section. Dynamic linking symbol table is loaded too, shared libraries as specified by DT_SHARED (or sth similar) entries are loaded using this same routine (it ends somewhere, use ldd to list). Dynamic symbols that are procedures have a PLT (procedure linkage table), global external variables (for any one of the functions, including shared library functions) are done through the GOT. The PLT is a table of code with addresses mixed in, where the jump address is initially a jump to the next address. The code there loads the function number, calls an OS service to ask for the real address (couldn't bind later...), that service maps it and returns the address. Address is replaced, and jumped to the call at that place (now using the CORRECT address just asked for) and the call is performed. This prevents a lot of linking overhead, but does incur a little performance hit each time a new function is called.

The GOT is just filled in with offsets of all sorts of objects :).

BTW, do note that the EBX register is the only one used for purposes other than calculation, it's used for the base of any given dynamic library. The GOT is at a specific location and can thus be loaded at that location statically, and linked statically. The offsets themselves change inside the table.

HTH, C&CW, Candy
Post Reply