Why “symbol@GOT” is not permitted on pie binary?












2















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.










share|improve this question




















  • 1





    Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

    – Jester
    Nov 20 '18 at 13:46






  • 1





    @Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

    – Jiwon
    Nov 20 '18 at 14:31






  • 3





    Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

    – Jester
    Nov 20 '18 at 14:53











  • @Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

    – Jiwon
    Nov 20 '18 at 16:47








  • 2





    Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

    – Margaret Bloom
    Nov 20 '18 at 17:02
















2















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.










share|improve this question




















  • 1





    Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

    – Jester
    Nov 20 '18 at 13:46






  • 1





    @Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

    – Jiwon
    Nov 20 '18 at 14:31






  • 3





    Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

    – Jester
    Nov 20 '18 at 14:53











  • @Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

    – Jiwon
    Nov 20 '18 at 16:47








  • 2





    Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

    – Margaret Bloom
    Nov 20 '18 at 17:02














2












2








2


1






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.










share|improve this question
















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.







linux assembly x86 position-independent-code got






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 17:22









Peter Cordes

123k17186313




123k17186313










asked Nov 20 '18 at 13:33









JiwonJiwon

310213




310213








  • 1





    Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

    – Jester
    Nov 20 '18 at 13:46






  • 1





    @Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

    – Jiwon
    Nov 20 '18 at 14:31






  • 3





    Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

    – Jester
    Nov 20 '18 at 14:53











  • @Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

    – Jiwon
    Nov 20 '18 at 16:47








  • 2





    Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

    – Margaret Bloom
    Nov 20 '18 at 17:02














  • 1





    Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

    – Jester
    Nov 20 '18 at 13:46






  • 1





    @Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

    – Jiwon
    Nov 20 '18 at 14:31






  • 3





    Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

    – Jester
    Nov 20 '18 at 14:53











  • @Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

    – Jiwon
    Nov 20 '18 at 16:47








  • 2





    Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

    – Margaret Bloom
    Nov 20 '18 at 17:02








1




1





Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

– Jester
Nov 20 '18 at 13:46





Loader does not usually write into code section as that would break sharing across processes which is important for libraries. It's not particularly useful for executables but since PIE is built on top of the same functionality it is not allowed.

– Jester
Nov 20 '18 at 13:46




1




1





@Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

– Jiwon
Nov 20 '18 at 14:31





@Jester But... loader write into code section when we use direct memory access. For example, When we use instruction like mov MY_SYMBOL, %eax and compile it into pie binary, address of MY_SYMBOL is not fixed until loading time. In this case, loader write address of MY_SYMBOL into <.text> section at loading time.

– Jiwon
Nov 20 '18 at 14:31




3




3





Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

– Jester
Nov 20 '18 at 14:53





Yeah, technically it would be possible but the whole point of a GOT is to avoid relocations in code. If you can live with relocations you don't need a GOT and can just use the simple relocation you showed.

– Jester
Nov 20 '18 at 14:53













@Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

– Jiwon
Nov 20 '18 at 16:47







@Jester Oh It make sence. Yes, you are right. We use GOT to avoid relocation in code, and accessing GOT section with relocaion is weird...like contradicting itself. Thank you for the comment!

– Jiwon
Nov 20 '18 at 16:47






2




2





Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

– Margaret Bloom
Nov 20 '18 at 17:02





Interesting question. This source has a comment about the GOT address being unknown for PICs. I don't know why that should be the case for a shared library, the local GOT is known. Maybe they are talking about the GOT of another module? Also lea is allowed (documented in the ABI). Finally, it seems the description of the algorithm is deceiving, the end of the .got section is subtracted. I can't think of any reason for this, right now.

– Margaret Bloom
Nov 20 '18 at 17:02












1 Answer
1






active

oldest

votes


















1














PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:



    call thunk
add $_GLOBAL_OFFSET_TABLE__, %eax
mov __progname@GOT(%eax), %eax
ret
thunk:
mov (%esp), %eax
ret


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:



mov    __progname(%rip), %rax
ret


Notice that both of these keep the text ‘pure’....






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53394184%2fwhy-symbolgot-is-not-permitted-on-pie-binary%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:



        call thunk
    add $_GLOBAL_OFFSET_TABLE__, %eax
    mov __progname@GOT(%eax), %eax
    ret
    thunk:
    mov (%esp), %eax
    ret


    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:



    mov    __progname(%rip), %rax
    ret


    Notice that both of these keep the text ‘pure’....






    share|improve this answer




























      1














      PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:



          call thunk
      add $_GLOBAL_OFFSET_TABLE__, %eax
      mov __progname@GOT(%eax), %eax
      ret
      thunk:
      mov (%esp), %eax
      ret


      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:



      mov    __progname(%rip), %rax
      ret


      Notice that both of these keep the text ‘pure’....






      share|improve this answer


























        1












        1








        1







        PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:



            call thunk
        add $_GLOBAL_OFFSET_TABLE__, %eax
        mov __progname@GOT(%eax), %eax
        ret
        thunk:
        mov (%esp), %eax
        ret


        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:



        mov    __progname(%rip), %rax
        ret


        Notice that both of these keep the text ‘pure’....






        share|improve this answer













        PIE is supposed to use pc-relative addressing; ia32 is crap at this, so you need to do something like:



            call thunk
        add $_GLOBAL_OFFSET_TABLE__, %eax
        mov __progname@GOT(%eax), %eax
        ret
        thunk:
        mov (%esp), %eax
        ret


        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:



        mov    __progname(%rip), %rax
        ret


        Notice that both of these keep the text ‘pure’....







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 20 '18 at 19:30









        mevetsmevets

        2,090618




        2,090618






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53394184%2fwhy-symbolgot-is-not-permitted-on-pie-binary%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            Npm cannot find a required file even through it is in the searched directory

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith