The main reason I have seen PIC being used under Linux is when you create an object that will be used by another system or many software (i.e. a system library or a library which is part of a software suite such as MySQL.)
For example, you can write modules for PHP, Apache, and probably MySQL, and those modules need to be loaded by those tools and that will happen at some "random" address and they will be able to execute their code with minimal work on the code. Actually, in most cases these systems check to see whether your module is a PIC (Position Independent Code, as queen3 underlined) module and if not they refuse to load your module.
This allows most of your code to run without having to do what is called relocations. A relocation is an addition to an address of a the base address where the code was loaded and that modifies the code of the library (it is perfectly safe though.) This is important for dynamic libraries since each time they are loaded by a different process, they may be given a different address (note that has nothing to do with security, only address space that's available to your process.) However, relocations means that each version is different since, as I just said, you modify the code that was loaded for each process and thus each process has a different version in memory (which means that the fact that the library is dynamically loaded does not do as much as it otherwise could!)
The PIC mechanism creates a table, as mentioned by others, that is specific to your process as is the read/write memory (.data) used by those libraries, but the rest of the library (the .text and .rodata sections) remains intact meaning that it can be used by many processes from that one location (although the address of that library may be different to the point of view of each process, note that is a side effect of what is called the MMU: Memory Management Unit, which can assign a virtual address to any physical address.)
In the old days, under systems such as the famous IRIX system from SGI, the mechanism was to pre-assign a base address for each dynamic library. That was a pre-relocation so that way each process would find that dynamic library at that one specific location making it truly shareable. But when you have hundreds of shared libraries, pre-allocating a virtual address to each one of them would make it nearly impossible to run large systems as we have today. And I won't even talk about the fact that one library may get upgraded and now bump in the one that was assigned the address right after... Only the MMU of the time were less versatile than those of today and PIC was not yet viewed as a good solution.
To answer your question in regard to mysql, the -DWITH_PIC is probably a good idea because many tools run all the time and all those libraries will be loaded once and reused by all the tools. So at run time, it will be faster. Without the PIC feature, it will certainly have to reload that same library over and over again, wasting a lot of time. So a few more Mb can save you millions of cycles per second and when you run a process 24/7, that's quite a bit of time!
I'm thinking that maybe a small example in assembly would better explain what we're talking about here...
When your code needs to jump to some place, the simplest is to use a jump instruction:
jmp $someplace
In this case, $someplace is called an absolute address. This is a problem since if you load your code at a different location (a different base address) then $someplace changes too. To palliate, we have relocations. This is a table tells the system to add the base address to $someplace so that way the jmp actually works as expected.
When using PIC, that jump instruction with an absolute address is transformed in one of two ways: jump through a table or jump using relative addresses.
jmp $function_offset[%ebx] ; jump to the table where function is defined at function_offset
bra $someplace ; this is relative to IP so no need to change anything
As you can see here, I use the special instruction bra (branch) instead of a jump to get the relative jump. This is possible if you are jumping to another place within the same section of code, although in some processors such jumping is very limited (i.e. -128 to +127 bytes!) but with newer processors, the limit is generally +/-2Gb.
The jmp (or jsr for jump to sub-routine, on INTEL it's the call instruction), however, will generally be used when jumping to a different function or outside the same section code. That is just a lot cleaner to handle inter-function calls.
In many ways, most of your code is already in PIC except:
- when you call another function (other than inline or intrinsic functions)
- when you access data
For data we have a similar problem, we want to load a value from an address with a mov:
mov %eax, [$my_data]
Here %my_data would be an absolute address which would require a relocation (i.e. the compiler would save the offset of $my_data compared to the start of the sections and on load the base address where the library gets loaded would be added to the location of the address in the mov instruction.)
This is where our table comes into play with the %ebx register. The start of the address is found at some specific offset in the table and it can be retrieved to access the data. This requires two instructions:
mov %eax, $data_pointer[%ebx]
mov %eax, $my_data_offset[%eax]
We first load the pointer to the start of the data buffer, then we load the data itself from that pointer. It's a bit slower, but the first load will be cached by the processor so re-accessing it over and over again will be instantaneous anyway (no actual memory access.)