6

Do different sections of libc (such as .text, .plt, .got, .bss, .rodata, and others) get loaded at the same offset relative to the libc base address every time?

I know the loader loads libc at a random location every time I run my program.

Thank you in advance.

jpaugh
  • 6,634
  • 4
  • 38
  • 90
masec
  • 584
  • 5
  • 16
  • 1
    Did you test it, perhaps by running `cat /proc/self/maps` several times? – Basile Starynkevitch Jan 19 '18 at 18:12
  • Yes I tried that, but `/proc/self/maps` only shows the images base addresses not their sections. I can find where `libc` and `ld` get loaded but still I have my question that whether their sections get loaded with the same offset every time. – masec Jan 19 '18 at 18:52

1 Answers1

3

I guess I found the answer to my own question. I wrote a pin-tool using Intel PIN that on every libc section get loaded outputs the section offset relative to the address of libc. Here are the sections having get loaded at same offsets with their corresponding offsets (the thing before - is the library name which is libc with its version and what comes after that is the section name):

libc.so.6-.note.gnu.build-id             0x0000000000000270
libc.so.6-.note.ABI-tag                  0x0000000000000294
libc.so.6-.gnu.hash                      0x00000000000002b8
libc.so.6-.dynsym                        0x0000000000003d80
libc.so.6-.dynstr                        0x0000000000010ff8
libc.so.6-.gnu.version                   0x00000000000169d8
libc.so.6-.gnu.version_d                 0x0000000000017b68
libc.so.6-.gnu.version_r                 0x0000000000017ee0
libc.so.6-.rela.dyn                      0x0000000000017f10
libc.so.6-.rela.plt                      0x000000000001f680
libc.so.6-.plt                           0x000000000001f7c0
libc.so.6-.plt.got                       0x000000000001f8a0
libc.so.6-.text                          0x000000000001f8b0
libc.so.6-__libc_freeres_fn              0x0000000000172b10
libc.so.6-__libc_thread_freeres_fn       0x0000000000175030
libc.so.6-.rodata                        0x0000000000175300
libc.so.6-.stapsdt.base                  0x0000000000196650
libc.so.6-.interp                        0x0000000000196660
libc.so.6-.eh_frame_hdr                  0x000000000019667c
libc.so.6-.eh_frame                      0x000000000019bb38
libc.so.6-.gcc_except_table              0x00000000001bc3cc
libc.so.6-.hash                          0x00000000001bc810
libc.so.6-.tdata                         0x00000000003c07c0
libc.so.6-.tbss                          0x00000000003c07d0
libc.so.6-.init_array                    0x00000000003c07d0
libc.so.6-__libc_subfreeres              0x00000000003c07e0
libc.so.6-__libc_atexit                  0x00000000003c08d8
libc.so.6-__libc_thread_subfreeres       0x00000000003c08e0
libc.so.6-.data.rel.ro                   0x00000000003c0900
libc.so.6-.dynamic                       0x00000000003c3ba0
libc.so.6-.got                           0x00000000003c3d80
libc.so.6-.got.plt                       0x00000000003c4000
libc.so.6-.data                          0x00000000003c4080
libc.so.6-.bss                           0x00000000003c5720

And there are indeed sections that get loaded at different offsets every time. You may see them in below. However, as I do not recognize them and to me not important, I would like to conclude that yes the sections we most concern about get loaded at the same offset each time the program runs.

libc.so.6-.note.stapsdt                  
libc.so.6-.gnu.warning.sigstack          
libc.so.6-.gnu.warning.sigreturn         
libc.so.6-.gnu.warning.siggetmask        
libc.so.6-.gnu.warning.tmpnam            
libc.so.6-.gnu.warning.tmpnam_r          
libc.so.6-.gnu.warning.tempnam           
libc.so.6-.gnu.warning.sys_errlist       
libc.so.6-.gnu.warning.sys_nerr          
libc.so.6-.gnu.warning.gets              
libc.so.6-.gnu.warning.getpw             
libc.so.6-.gnu.warning.re_max_failures   
libc.so.6-.gnu.warning.lchmod            
libc.so.6-.gnu.warning.getwd             
libc.so.6-.gnu.warning.sstk              
libc.so.6-.gnu.warning.revoke            
libc.so.6-.gnu.warning.mktemp            
libc.so.6-.gnu.warning.gtty              
libc.so.6-.gnu.warning.stty              
libc.so.6-.gnu.warning.chflags           
libc.so.6-.gnu.warning.fchflags          
libc.so.6-.gnu.warning.__compat_bdflush  
libc.so.6-.gnu.warning.__memset_zero_constant_len_parameter
libc.so.6-.gnu.warning.__gets_chk        
libc.so.6-.gnu.warning.inet6_option_space 
libc.so.6-.gnu.warning.inet6_option_init 
libc.so.6-.gnu.warning.inet6_option_append 
libc.so.6-.gnu.warning.inet6_option_alloc 
libc.so.6-.gnu.warning.inet6_option_next 
libc.so.6-.gnu.warning.inet6_option_find 
libc.so.6-.gnu.warning.getmsg            
libc.so.6-.gnu.warning.putmsg            
libc.so.6-.gnu.warning.fattach           
libc.so.6-.gnu.warning.fdetach           
libc.so.6-.gnu.warning.setlogin          
libc.so.6-.gnu_debuglink                 
libc.so.6-.shstrtab                      
masec
  • 584
  • 5
  • 16
  • This probably varies based on which compiler/linker/operating system combination you're using. If it's specified (either in the spec, or a compiler manual), it'd be good to have a link. – jpaugh Jan 19 '18 at 19:58
  • You are right I guess. I used `gcc` in `64-bit Ubuntu Linux`. If someone else tried other compilers or linkers and had different answer please post your answer as well. – masec Jan 19 '18 at 20:02
  • Unless it is restricted somehow by the spec, it very likely may differ between different versions of `gcc`, especially when considering really old versions. IDK, though: I try to stay away from C, usually! ;-) – jpaugh Jan 19 '18 at 20:05
  • @jpaugh: For RIP-relative addressing of static data in the BSS and data segments to work without text relocation, they have to be mapped at the same relative address to the text segment. The ELF object as a whole is ASLRed, not the individual segments relative to each other. One of the big benefits of RIP-relative addressing is PIC code which doesn't need to use the GOT for everything, and which doesn't need relocation fixups after loading, so yes you can be sure this is how it's designed to work. – Peter Cordes Jan 20 '18 at 02:53
  • 1
    I think the "unimportant" sections aren't part of any segment that the program-loader maps; are you sure they're getting mapped at all, and you're calculating something sane for them? ([segment vs. section](https://stackoverflow.com/questions/14361248/whats-the-difference-of-section-and-segment-in-elf-file-format).) – Peter Cordes Jan 20 '18 at 02:53
  • I used pin tool for that and in my instrumentation I just output the address of each section of each image in PIN terminology. I am sure that PIN only instrument all images that get loaded but I am not sure about sections. I just iterated through all sections of the `libc` image. – masec Jan 21 '18 at 18:02