Compiling this C code:
#include <stdio.h>
const char code[] __attribute__((section(".mySection"))) = "xb8x0dx00x00x00xc3";
int main(int argc, char **argv)
{
int val = ((int(*)(void))code)();
printf("val %dn", val);
}
together with this ld script:
MEMORY
{
my_region (RWX) : ORIGIN = 0x405340, LENGTH = 4K
}
SECTIONS
{
.mySegment 0x405340 : {KEEP(*(.mySection))} > my_region
}
as:
gcc link.ld t79.c
leads to:
/usr/bin/ld: warning: link.ld contains output sections; did you forget -T?
/usr/bin/ld: internal error ../../ld/ldlang.c 6101
collect2: error: ld returned 1 exit status
Why? How to fix?
ld version: 2.34
gcc version: 9.4.0
uname -a:
Linux xxx 5.15.0-25-generic #25~20.04.2-Ubuntu SMP Mon Apr 11 08:31:42 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
UPD: the internal error ../../ld/ldlang.c 6101
comes from here (function lang_size_relro_segment_1
):
ASSERT (desired_end >= seg->base);
2
Answers
The
internal error ../../ld/ldlang.c 6101
comes fromRWX
. I was mistakenly thinking thatW
stands for "write", whileW
stands for "read/write".In case of
WX
the output is the following:Instead of fixing it I use GCC exploit:
I’m not sure what you want to achieve but the direct way to solve this problem would be:
-T
to order the linker script to be read. That will lead you to the real problem.-nostartfiles
, so togethergcc -T link.ld t79.c -nostartfiles
, to get rid of the undefined references, as the standard system startup files than won’t be used when linking. The standard system libraries will be used normally.SECTIONS
part from the linker script to avoid collisions of.mySegment
with the other sections.After this kind of a brute force solution the program will be compiled and linked successfully, you’ll get a printout — I get a
val 13
— and than the program will crash due to a segmentation fault.