Why “symbol@GOT” is not permitted on pie binary?
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 likemov __progname@GOT(%ebx), %eax
.
linux assembly x86 position-independent-code got
add a comment |
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 likemov __progname@GOT(%ebx), %eax
.
linux assembly x86 position-independent-code got
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 likemov MY_SYMBOL, %eax
and compile it into pie binary, address ofMY_SYMBOL
is not fixed until loading time. In this case, loader write address ofMY_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? Alsolea
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
add a comment |
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 likemov __progname@GOT(%ebx), %eax
.
linux assembly x86 position-independent-code got
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 likemov __progname@GOT(%ebx), %eax
.
linux assembly x86 position-independent-code got
linux assembly x86 position-independent-code got
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 likemov MY_SYMBOL, %eax
and compile it into pie binary, address ofMY_SYMBOL
is not fixed until loading time. In this case, loader write address ofMY_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? Alsolea
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
add a comment |
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 likemov MY_SYMBOL, %eax
and compile it into pie binary, address ofMY_SYMBOL
is not fixed until loading time. In this case, loader write address ofMY_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? Alsolea
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
add a comment |
1 Answer
1
active
oldest
votes
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’....
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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’....
add a comment |
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’....
add a comment |
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’....
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’....
answered Nov 20 '18 at 19:30


mevetsmevets
2,090618
2,090618
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 ofMY_SYMBOL
is not fixed until loading time. In this case, loader write address ofMY_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