Practical Session 8
Position Independent Position Independent Code- Code-
self sufficiency of combining program self sufficiency of combining program
• Position Independent Code (PIC) program has everything it needs internally
• PIC can be placed somewhere in memory, executes properly regardless of its absolute address
• PIC can be added to any other program, without fear that it might not work
• No direct usage of labels
• Only relative jumps (“call”)
• One section only
• No library functions only system calls
Position Independent Position Independent Code- Code-
requirements requirements
No direct usage of labelsNo direct usage of labels
Labels are resolved by the assembler and linker at compile time to an absolute address.
If the code is moved (in an appropriate section), the absolute address that was calculated before the moving wont be correct any more.
No direct usage of labelsNo direct usage of labels
An absolute address of STR1 and STR2 would be resolved based on the relative address of STR1 and STR2 in .rodata section (which may change if all the code would be moved)
We can use only relative jumps because the code we wish to jump to may change its position.
If all the code changes its position, relative jumps are still valid, because the address difference is preserved.
We can use “call” instruction because it makes a relative jump to the function (which means that the new IP (after “call”) will be the old IP (before “call”) plus a number (may be negative) with was the address difference of the
two places calculated by the assembler).
Only relative jumpsOnly relative jumps
Only relative jumps - exampleOnly relative jumps - example• The first column (from the left) is simply the line number in the listing and is otherwise meaningless • The second column is the relative address, in hex, of where the code will be placed in memory• The third column is the actual compiled code
• For the normal type of call in 32-bit mode (relative near call), the binary code for ‘CALL myFunc’ is the opcode E8 followed by a 4-byte value that specifies the target address, relative to the next instruction after the call.
Address of myFunc label = 0x1F Address of the next instruction after the call (i.e. ‘mov [answer], eax’) is 0xA 0x1F-0xA=0x15, and we get exactly the binary code written here ‘E815000000’
One section onlyOne section only
We put all the code in a single section – .text (read-
only) or .data (read-write).
Both .text and .data sections may contain any valid assembly instruction.
Usage of a single section gives us a possibility to calculate a difference between each pair of code instructions, and thus execute relative jumps.
No library functionsNo library functionsonly system callsonly system calls
We don’t know if and where the library functions are .Thus there are no “printf” “gets” and so on…
To perform I/O operation we have to use the Linux system calls because INT 0x80 isn’t a regular procedure - it is called via the interrupt table which is static.
• Since ‘call’ instruction executes a relative jump, we may ‘call’ functions that are defined in PIC
• ‘call’ instruction pushes the return address at run-time
Thus we may calculate a run-time address of any label relatively to ‘call’ return address
Finding a code address at run-timeFinding a code address at run-time
Finding a code address at run-timeFinding a code address at run-time
get_my_loc function gets the address of ‘next_i’ label at run-time
get_my_loc: call next_i
next_i: pop edx ret
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
ESPstack
Using strings – PIC exampleUsing strings – PIC example
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
ESP
address of ‘sub edx, next_i-name’
stack
Using strings – PIC exampleUsing strings – PIC example
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
ESP
address of ‘sub edx, next_i-name’
address of ‘next_i’
stack
Using strings – PIC exampleUsing strings – PIC example
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ; edx gets ‘next_i’ address ret_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
ESP
address of ‘sub edx, next_i-name’
stack
Using strings – PIC exampleUsing strings – PIC example
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret ; EIP gets address of ‘sub edx, next_i-name’_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
ESPstack
Using strings – PIC exampleUsing strings – PIC example
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret_start:
call get_my_loc sub edx, next_i – name ; edx = ‘next_i’ address – (‘next_i’ address – ‘name’ address)
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
Using strings – PIC exampleUsing strings – PIC example
the address difference between “next_i” and “name” is constant even if the code changes it’s position
section .text
name: db "Moshe",10,0nameLen equ $ - name
global _startget_my_loc:
call next_inext_i: pop edx ret_start:
call get_my_loc sub edx, next_i – name
mov ecx, edxmov edx, nameLenmov eax, 4
mov ebx, 1int 80hmov eax, 1int 80h
Using strings – PIC exampleUsing strings – PIC example
why we may use ‘nameLen’ label directly ?
Using strings – PIC exampleUsing strings – PIC example
0x0C = ‘next_i’ – ‘name’
>nasm -f elf sample.s -l sample.lst