Here is sample assembly file, test.s
.global main
main:
mov __progname@GOT, %eax // failed to compile
mov __progname@GOT(%ebx), %eax //succeed to compile
I tried compiling it with -pie
flag, but failed.
$ gcc -pie -o test test.s
osboxes@osboxes:/mnt/hgfs/VM_Shared/Reassemblabla/src$ gcc -pie -o test test.s
/usr/bin/ld: /tmp/ccPGMLlH.o: direct GOT relocation R_386_GOT32X against `__progname' without base register can not be used when making a shared object
/usr/bin/ld: failed to set dynamic section sizes: File format not recognized
collect2: error: ld returned 1 exit status
Error said, In pie binary, access to GOT
entry is only available using base register.
Question.
I don't know why compiler is complaining like above.
More specifically, why __progname@GOT
addressing is not permitted on pie binary?
My opinion.
Loader knows the address of __progname@GOT
in loading time of pie binary.
So, loader can simply write this address at location of __progname@GOT
in loading time.
That's what loader can do.
So I cannot understand why compiler insist on register-relative accessing like
mov __progname@GOT(%ebx), %eax
.
PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:
Notice offset from this program address to the _GLOBAL_OFFSET_TABLE__ is computed to reference GOT. Thus the program can be loaded (as opposed to linked or located) at any address, and will find the GOT, and all variables, because the relative offset is the same. For reference, the amd64 version of the above is something like:
Notice that both of these keep the text ‘pure’....